From aad66423ea99f72d673bf01da57fc59e4465d205 Mon Sep 17 00:00:00 2001 From: Lev Brouk Date: Sun, 19 Feb 2023 05:43:36 -0800 Subject: [PATCH] cached store changes --- apps/app.go | 4 + apps/manifest.go | 4 + build/custom.mk | 4 +- go.mod | 118 +-- go.sum | 739 +++++++++++++----- server/appservices/kv.go | 4 +- server/appservices/oauth2.go | 17 +- server/appservices/service.go | 31 +- server/appservices/subscriptions.go | 56 +- server/builtin/debug_kv_create.go | 2 +- server/builtin/debug_kv_edit.go | 2 +- server/builtin/debug_kv_info.go | 2 +- server/builtin/debug_store_pollute.go | 2 +- server/config/config.go | 18 +- server/config/service.go | 20 + server/config/test_service.go | 2 + .../{mock_appstore.go => mock_app_store.go} | 75 +- ...{mock_session.go => mock_session_store.go} | 74 +- server/plugin.go | 33 +- server/proxy/bindings_test.go | 9 +- server/proxy/invoke_oauth2.go | 4 +- server/proxy/notify.go | 2 +- server/proxy/synchronize.go | 10 +- server/proxy/uninstall.go | 139 +++- server/proxy/uninstall_test.go | 158 ++++ server/proxy/update_app_listing.go | 2 +- server/session/session.go | 10 +- server/session/session_test.go | 47 +- server/store/appkv.go | 31 +- server/store/apps.go | 241 ++---- server/store/cached.go | 124 +++ server/store/cached_cluster.go | 109 +++ server/store/cached_mutex.go | 126 +++ server/store/cached_mutex_test.go | 170 ++++ server/store/cached_simple.go | 233 ++++++ server/store/cached_single_writer.go | 170 ++++ server/store/cached_test.go | 37 + server/store/cached_test_memory_store.go | 47 ++ server/store/kv_debug_info.go | 50 +- server/store/manifest.go | 278 ++----- server/store/migration.go | 19 + server/store/oauth2.go | 47 +- server/store/oauth2_test.go | 47 +- server/store/pkg.go | 13 + server/store/service.go | 143 ++-- server/store/session.go | 72 +- server/store/subscriptions.go | 147 +--- server/store/subscriptions_test.go | 108 --- test/restapitest/bindings.go | 1 - test/restapitest/kv.go | 50 +- test/restapitest/oauth2.go | 1 - test/restapitest/subscribe.go | 56 +- test/restapitest/uninstall.go | 134 ++-- utils/logger.go | 11 + utils/plugin_logger.go | 4 +- 55 files changed, 2655 insertions(+), 1402 deletions(-) rename server/mocks/mock_store/{mock_appstore.go => mock_app_store.go} (51%) rename server/mocks/mock_store/{mock_session.go => mock_session_store.go} (51%) create mode 100644 server/proxy/uninstall_test.go create mode 100644 server/store/cached.go create mode 100644 server/store/cached_cluster.go create mode 100644 server/store/cached_mutex.go create mode 100644 server/store/cached_mutex_test.go create mode 100644 server/store/cached_simple.go create mode 100644 server/store/cached_single_writer.go create mode 100644 server/store/cached_test.go create mode 100644 server/store/cached_test_memory_store.go create mode 100644 server/store/migration.go create mode 100644 server/store/pkg.go delete mode 100644 server/store/subscriptions_test.go diff --git a/apps/app.go b/apps/app.go index dfa6b9183..63e75beb5 100644 --- a/apps/app.go +++ b/apps/app.go @@ -120,3 +120,7 @@ type ListedApp struct { IconURL string `json:"icon_url,omitempty"` Labels []model.MarketplaceLabel `json:"labels,omitempty"` } + +func (app App) Clone() *App { + return &app +} diff --git a/apps/manifest.go b/apps/manifest.go index f49bc611d..24227b4d7 100644 --- a/apps/manifest.go +++ b/apps/manifest.go @@ -202,6 +202,10 @@ func (m Manifest) Validate() error { return result } +func (m Manifest) Clone() *Manifest { + return &m +} + // AppID is a globally unique identifier that represents a Mattermost App. // An AppID is restricted to no more than 32 ASCII letters, numbers, '-', or '_'. type AppID string diff --git a/build/custom.mk b/build/custom.mk index 81107c93f..d1165ea76 100644 --- a/build/custom.mk +++ b/build/custom.mk @@ -25,9 +25,9 @@ mock: ifneq ($(HAS_SERVER),) go install github.com/golang/mock/mockgen@v1.6.0 mockgen -destination server/mocks/mock_proxy/mock_expand_getter.go github.com/mattermost/mattermost-plugin-apps/server/proxy ExpandGetter + mockgen -destination server/mocks/mock_store/mock_app_store.go github.com/mattermost/mattermost-plugin-apps/server/store Apps + mockgen -destination server/mocks/mock_store/mock_session_store.go github.com/mattermost/mattermost-plugin-apps/server/store Sessions mockgen -destination server/mocks/mock_upstream/mock_upstream.go github.com/mattermost/mattermost-plugin-apps/upstream Upstream - mockgen -destination server/mocks/mock_store/mock_appstore.go github.com/mattermost/mattermost-plugin-apps/server/store AppStore - mockgen -destination server/mocks/mock_store/mock_session.go github.com/mattermost/mattermost-plugin-apps/server/store SessionStore endif ## Generates mock golang interfaces for testing diff --git a/go.mod b/go.mod index c9b998df5..0e2b5b6c3 100644 --- a/go.mod +++ b/go.mod @@ -2,39 +2,41 @@ module github.com/mattermost/mattermost-plugin-apps go 1.18 +// replace github.com/mattermost/mattermost-server/v6 => ../mattermost-server + require ( - github.com/aws/aws-lambda-go v1.37.0 - github.com/aws/aws-sdk-go v1.44.190 - github.com/awslabs/aws-lambda-go-api-proxy v0.13.3 + github.com/aws/aws-lambda-go v1.19.1 + github.com/aws/aws-sdk-go v1.44.173 + github.com/awslabs/aws-lambda-go-api-proxy v0.13.2 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.5.9 + github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e github.com/gorilla/mux v1.8.0 - github.com/hashicorp/go-getter v1.6.2 + github.com/hashicorp/go-getter v1.5.5 github.com/hashicorp/go-multierror v1.1.1 github.com/mattermost/mattermost-plugin-api v0.1.1 - // mmgoget: github.com/mattermost/mattermost-server/v6@v7.7.0 is replaced by -> github.com/mattermost/mattermost-server/v6@ea08d47f60 - github.com/mattermost/mattermost-server/v6 v6.0.0-20230113170349-ea08d47f6051 - github.com/nicksnyder/go-i18n/v2 v2.2.1 - github.com/openfaas/faas-cli v0.0.0-20230119133646-fea2bf5a6d0c + github.com/mattermost/mattermost-server/v6 v6.0.0-20230205103718-6d8da29d69e6 + github.com/nicksnyder/go-i18n/v2 v2.2.0 + github.com/openfaas/faas-cli v0.0.0-20210705110531-a230119be00f github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.1 - go.uber.org/zap v1.24.0 + go.uber.org/zap v1.17.0 golang.org/x/crypto v0.5.0 - golang.org/x/oauth2 v0.4.0 + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 gopkg.in/yaml.v3 v3.0.1 ) require ( cloud.google.com/go v0.105.0 // indirect - cloud.google.com/go/compute v1.12.1 // indirect + cloud.google.com/go/compute v1.13.0 // indirect cloud.google.com/go/compute/metadata v0.2.1 // indirect - cloud.google.com/go/iam v0.7.0 // indirect + cloud.google.com/go/iam v0.8.0 // indirect cloud.google.com/go/storage v1.27.0 // indirect code.sajari.com/docconv v1.3.5 // indirect github.com/JalfResi/justext v0.0.0-20221106200834-be571e3e3052 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/PuerkitoBio/goquery v1.8.0 // indirect github.com/RoaringBitmap/roaring v1.2.1 // indirect github.com/advancedlogic/GoOse v0.0.0-20210820140952-9d5822d4a625 // indirect @@ -44,32 +46,32 @@ require ( github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect - github.com/bits-and-blooms/bitset v1.3.3 // indirect + github.com/bits-and-blooms/bitset v1.4.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.3.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/blevesearch/bleve/v2 v2.3.6-0.20221111171245-56dc9b25507e // indirect + github.com/blevesearch/bleve/v2 v2.3.6 // indirect github.com/blevesearch/bleve_index_api v1.0.5 // indirect - github.com/blevesearch/geo v0.1.15 // indirect + github.com/blevesearch/geo v0.1.17 // indirect github.com/blevesearch/go-porterstemmer v1.0.3 // indirect github.com/blevesearch/gtreap v0.1.1 // indirect github.com/blevesearch/mmap-go v1.0.4 // indirect github.com/blevesearch/scorch_segment_api/v2 v2.1.4 // indirect - github.com/blevesearch/segment v0.9.0 // indirect + github.com/blevesearch/segment v0.9.1 // indirect github.com/blevesearch/snowballstem v0.9.0 // indirect - github.com/blevesearch/upsidedown_store_api v1.0.1 // indirect + github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect github.com/blevesearch/vellum v1.0.9 // indirect github.com/blevesearch/zapx/v11 v11.3.7 // indirect github.com/blevesearch/zapx/v12 v12.3.7 // indirect github.com/blevesearch/zapx/v13 v13.3.7 // indirect github.com/blevesearch/zapx/v14 v14.3.7 // indirect - github.com/blevesearch/zapx/v15 v15.3.7 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/blevesearch/zapx/v15 v15.3.8 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/disintegration/imaging v1.6.2 // indirect - github.com/drone/envsubst v1.0.3 // indirect + github.com/drone/envsubst v1.0.2 // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect @@ -78,66 +80,68 @@ require ( github.com/felixge/httpsnoop v1.0.3 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/getsentry/sentry-go v0.15.0 // indirect + github.com/getsentry/sentry-go v0.16.0 // indirect github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573 // indirect github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/golang-migrate/migrate/v4 v4.15.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.6.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/gorilla/css v1.0.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/graph-gophers/dataloader/v6 v6.0.0 // indirect - github.com/graph-gophers/graphql-go v1.4.0 // indirect + github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a // indirect github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.3.1 // indirect - github.com/hashicorp/go-plugin v1.4.6 // indirect + github.com/hashicorp/go-hclog v1.4.0 // indirect + github.com/hashicorp/go-plugin v1.4.8 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.2.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.1 // indirect + github.com/klauspost/compress v1.15.14 // indirect + github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/klauspost/pgzip v1.2.5 // indirect - github.com/kr/pretty v0.3.1 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 // indirect github.com/levigross/exp-html v0.0.0-20120902181939-8df60c69a8f5 // indirect github.com/lib/pq v1.10.7 // indirect + github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect github.com/mattermost/gziphandler v0.0.1 // indirect github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect - github.com/mattermost/logr/v2 v2.0.15 // indirect + github.com/mattermost/logr/v2 v2.0.16 // indirect + github.com/mattermost/mattermost-plugin-playbooks/client v0.7.0 // indirect github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e // indirect github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 // indirect github.com/mattermost/squirrel v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mholt/archiver/v3 v3.5.1 // indirect github.com/microcosm-cc/bluemonday v1.0.21 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minio-go/v7 v7.0.43 // indirect + github.com/minio/minio-go/v7 v7.0.45 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -152,15 +156,15 @@ require ( github.com/otiai10/gosseract/v2 v2.4.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/philhofer/fwd v1.1.1 // indirect + github.com/philhofer/fwd v1.1.2 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/reflog/dateconstraints v0.2.1 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.3 // indirect github.com/rivo/uniseg v0.4.3 // indirect - github.com/rs/cors v1.8.2 // indirect + github.com/rs/cors v1.8.3 // indirect github.com/rs/xid v1.4.0 // indirect github.com/rudderlabs/analytics-go v3.3.3+incompatible // indirect github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect @@ -169,18 +173,18 @@ require ( github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/splitio/go-client/v6 v6.2.1 // indirect - github.com/splitio/go-split-commons/v4 v4.2.2 // indirect + github.com/splitio/go-split-commons/v4 v4.2.3 // indirect github.com/splitio/go-toolkit/v5 v5.2.2 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/throttled/throttled v2.2.5+incompatible // indirect - github.com/tidwall/gjson v1.14.3 // indirect + github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - github.com/tinylib/msgp v1.1.6 // indirect + github.com/tinylib/msgp v1.1.8 // indirect github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect - github.com/ulikunitz/xz v0.5.10 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wiggin77/merror v1.0.4 // indirect @@ -189,35 +193,35 @@ require ( github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect github.com/yuin/goldmark v1.5.3 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.opencensus.io v0.23.0 // indirect + go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.7.0 // indirect - golang.org/x/image v0.1.0 // indirect + golang.org/x/image v0.3.0 // indirect golang.org/x/mod v0.7.0 // indirect golang.org/x/net v0.5.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect - golang.org/x/tools v0.3.0 // indirect + golang.org/x/tools v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.102.0 // indirect + google.golang.org/api v0.103.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 // indirect - google.golang.org/grpc v1.50.1 // indirect + google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf // indirect + google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/mail.v2 v2.3.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - lukechampine.com/uint128 v1.1.1 // indirect - modernc.org/cc/v3 v3.36.0 // indirect - modernc.org/ccgo/v3 v3.16.6 // indirect - modernc.org/libc v1.16.7 // indirect - modernc.org/mathutil v1.4.1 // indirect - modernc.org/memory v1.1.1 // indirect - modernc.org/opt v0.1.1 // indirect - modernc.org/sqlite v1.18.0 // indirect - modernc.org/strutil v1.1.1 // indirect - modernc.org/token v1.0.0 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.2 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.20.1 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 309b253ad..ee145e9be 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +cloud.google.com/go v0.37.1/go.mod h1:SAbnLi6YTSPKSI0dTUEOVLCkyPfKXK8n4ibqiMoj4ok= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= @@ -16,6 +17,8 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 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/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= @@ -41,21 +44,22 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/errorreporting v0.2.0/go.mod h1:QkYzg92wgpJ0ChLdcO5LhtCEyYwq0tIa+jLrj6Nh5ME= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/spanner v1.9.0/go.mod h1:xvlEn0NZ5v1iJPYsBnUVRDNvccDxsBTEi16pJRKQVws= cloud.google.com/go/spanner v1.28.0/go.mod h1:7m6mtQZn/hMbMfx62ct5EWrGND4DNqkXyrmBPRS+OJo= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= @@ -64,8 +68,10 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +code.sajari.com/docconv v1.1.1-0.20210427001343-7b3472bc323a/go.mod h1:KPNt2zuWplps1W0TpOb6ltHj4Xu+j6h7a+YkqGHrxQE= code.sajari.com/docconv v1.3.5 h1:RBBs6aT3/5gHHWzAaxBj85e3ozsu05s2kAslhW7i+Ag= code.sajari.com/docconv v1.3.5/go.mod h1:EDkTrwa2yO2O9EbVpD3dlHXDVcxbfKDWnDNE/8vbbP8= +contrib.go.opencensus.io/exporter/ocagent v0.4.9/go.mod h1:ueLzZcP7LPhPulEBukGn4aLh7Mx9YJwpVJ9nL2FYltw= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= @@ -73,14 +79,18 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v26.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v11.5.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= @@ -96,19 +106,29 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v6 v6.1.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/HdrHistogram/hdrhistogram-go v0.9.0 h1:dpujRju0R4M/QZzcnR1LH1qm+TVG3UzkWdp5tH1WMcg= +github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4= github.com/JalfResi/justext v0.0.0-20170829062021-c0282dea7198/go.mod h1:0SURuH1rsE8aVWvutuMZghRNrNrYEUzibzJfhEYR8L0= github.com/JalfResi/justext v0.0.0-20221106200834-be571e3e3052 h1:8T2zMbhLBbH9514PIQVHdsGhypMrsB4CxwbldKA9sBA= github.com/JalfResi/justext v0.0.0-20221106200834-be571e3e3052/go.mod h1:0SURuH1rsE8aVWvutuMZghRNrNrYEUzibzJfhEYR8L0= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -135,21 +155,30 @@ github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:m github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PaulARoy/azurestoragecache v0.0.0-20170906084534-3c249a3ba788/go.mod h1:lY1dZd8HBzJ10eqKERHn3CU59tfhzcAVb2c0ZhIWSOk= github.com/PuerkitoBio/goquery v1.4.1/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/PuerkitoBio/goquery v1.7.0/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= +github.com/RoaringBitmap/roaring v0.8.0/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I= github.com/RoaringBitmap/roaring v1.2.1 h1:58/LJlg/81wfEHd5L9qsHduznOIhyv4qb1yWcSvVq9A= github.com/RoaringBitmap/roaring v1.2.1/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA= -github.com/Shopify/goreferrer v0.0.0-20210630161223-536fa16abd6f/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/advancedlogic/GoOse v0.0.0-20191112112754-e742535969c1/go.mod h1:f3HCSN1fBWjcpGtXyM119MJgeQl838v6so/PQOqvE1w= +github.com/advancedlogic/GoOse v0.0.0-20200830213114-1225d531e0ad/go.mod h1:f3HCSN1fBWjcpGtXyM119MJgeQl838v6so/PQOqvE1w= github.com/advancedlogic/GoOse v0.0.0-20210820140952-9d5822d4a625 h1:LZIP5Bj5poWWRZ8fcL4ZwCupb4FwcTFK2RCTxkGnCX8= github.com/advancedlogic/GoOse v0.0.0-20210820140952-9d5822d4a625/go.mod h1:f3HCSN1fBWjcpGtXyM119MJgeQl838v6so/PQOqvE1w= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -157,10 +186,13 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexellis/go-execute v0.0.0-20191207085904-961405ea7544/go.mod h1:zfRbgnPVxXCSpiKrg1CE72hNUWInqxExiaz2D9ppTts= +github.com/alexellis/hmac v0.0.0-20180624210714-d5d71edd7bc7/go.mod h1:uAbpy8G7sjNB4qYdY6ymf5OIQ+TLDPApBYiR0Vc3lhk= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= @@ -170,8 +202,11 @@ github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x0 github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY= github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/araddon/dateparse v0.0.0-20180729174819-cfd92a431d0e/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA= @@ -179,18 +214,25 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoU github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= +github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1 h1:9h8f71kuF1pqovnn9h7LTHLEjxzyQaj0j1rQq5nsMM4= github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1/go.mod h1:noBAuukeYOXa0aXGqxr24tADqkwDO2KRD15FsuaZ5a8= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-lambda-go v1.19.1 h1:5iUHbIZ2sG6Yq/J1IN3sWm3+vAB1CWwhI21NffLNuNI= github.com/aws/aws-lambda-go v1.19.1/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= -github.com/aws/aws-lambda-go v1.37.0 h1:WXkQ/xhIcXZZ2P5ZBEw+bbAKeCEcb5NtiYpSwVVzIXg= -github.com/aws/aws-lambda-go v1.37.0/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.44.190 h1:QC+Pf/Ooj7Waf2obOPZbIQOqr00hy4h54j3ZK9mvHcc= -github.com/aws/aws-sdk-go v1.44.190/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.19.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.38.67/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.44.173 h1:8kXIxvQnBpGhmR3Eof6SnCKgR0q5/L/3Qbv9vAC5wic= +github.com/aws/aws-sdk-go v1.44.173/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU= @@ -217,14 +259,13 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.6.1/go.mod h1:hLZ/AnkIKHLuPGjEiyghNE github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= github.com/aws/smithy-go v1.7.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/awslabs/aws-lambda-go-api-proxy v0.13.3 h1:kGtltTONdJa0Bmot9phYw3ucCg2SExj6mH00I1aga8Y= -github.com/awslabs/aws-lambda-go-api-proxy v0.13.3/go.mod h1:S5mIpII0ID7L9o6bN8VNwO69UpWMg/j4IympsjtKghE= +github.com/awslabs/aws-lambda-go-api-proxy v0.13.2 h1:Sy8mCKR8GKRRQBU5jt5p6KHD9JPltl5ClfJMwhx35BI= +github.com/awslabs/aws-lambda-go-api-proxy v0.13.2/go.mod h1:+c4BkN5CUEoXrdrOmBruhtRIcmwXWQBu6vz6xCFAvdA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 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= @@ -236,41 +277,49 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCS github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.3.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bitset v1.3.3 h1:R1XWiopGiXf66xygsiLpzLo67xEYvMkHw3w+rCOSAwg= -github.com/bits-and-blooms/bitset v1.3.3/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.4.0 h1:+YZ8ePm+He2pU3dZlIZiOeAKfrBkXi1lSrXJ/Xzgbu8= +github.com/bits-and-blooms/bitset v1.4.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bloom/v3 v3.3.1 h1:K2+A19bXT8gJR5mU7y+1yW6hsKfNCjcP2uNfLFKncjQ= github.com/bits-and-blooms/bloom/v3 v3.3.1/go.mod h1:bhUUknWd5khVbTe4UgMCSiOOVJzr3tMoijSK3WwvW90= 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/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/blevesearch/bleve/v2 v2.3.6-0.20221111171245-56dc9b25507e h1:r/cWPLUPgAM3SWWniQ6j0Hzb++h+uEycDD9UOUuC1Vk= -github.com/blevesearch/bleve/v2 v2.3.6-0.20221111171245-56dc9b25507e/go.mod h1:mfCWvuwg/XnPVZHEejATm5TyFqyeLmm8p9Y3xDvwz4k= -github.com/blevesearch/bleve_index_api v1.0.3/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4= +github.com/blevesearch/bleve v1.0.14/go.mod h1:e/LJTr+E7EaoVdkQZTfoz7dt4KoDNvDbLb8MSKuNTLQ= +github.com/blevesearch/bleve/v2 v2.3.6 h1:NlntUHcV5CSWIhpugx4d/BRMGCiaoI8ZZXrXlahzNq4= +github.com/blevesearch/bleve/v2 v2.3.6/go.mod h1:JM2legf1cKVkdV8Ehu7msKIOKC0McSw0Q16Fmv9vsW4= github.com/blevesearch/bleve_index_api v1.0.5 h1:Lc986kpC4Z0/n1g3gg8ul7H+lxgOQPcXb9SxvQGu+tw= github.com/blevesearch/bleve_index_api v1.0.5/go.mod h1:YXMDwaXFFXwncRS8UobWs7nvo0DmusriM1nztTlj1ms= -github.com/blevesearch/geo v0.1.15 h1:0NybEduqE5fduFRYiUKF0uqybAIFKXYjkBdXKYn7oA4= -github.com/blevesearch/geo v0.1.15/go.mod h1:cRIvqCdk3cgMhGeHNNe6yPzb+w56otxbfo1FBJfR2Pc= +github.com/blevesearch/blevex v1.0.0/go.mod h1:2rNVqoG2BZI8t1/P1awgTKnGlx5MP9ZbtEciQaNhswc= +github.com/blevesearch/cld2 v0.0.0-20200327141045-8b5f551d37f5/go.mod h1:PN0QNTLs9+j1bKy3d/GB/59wsNBFC4sWLWG3k69lWbc= +github.com/blevesearch/geo v0.1.17 h1:AguzI6/5mHXapzB0gE9IKWo+wWPHZmXZoscHcjFgAFA= +github.com/blevesearch/geo v0.1.17/go.mod h1:uRMGWG0HJYfWfFJpK3zTdnnr1K+ksZTuWKhXeSokfnM= github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y= github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk= +github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA= github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc= github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= github.com/blevesearch/scorch_segment_api/v2 v2.1.4 h1:LmGmo5twU3gV+natJbKmOktS9eMhokPGKWuR+jX84vk= github.com/blevesearch/scorch_segment_api/v2 v2.1.4/go.mod h1:PgVnbbg/t1UkgezPDu8EHLi1BHQ17xUwsFdU6NnOYS0= -github.com/blevesearch/segment v0.9.0 h1:5lG7yBCx98or7gK2cHMKPukPZ/31Kag7nONpoBt22Ac= github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ= +github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= +github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s= github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs= -github.com/blevesearch/upsidedown_store_api v1.0.1 h1:1SYRwyoFLwG3sj0ed89RLtM15amfX2pXlYbFOnF8zNU= -github.com/blevesearch/upsidedown_store_api v1.0.1/go.mod h1:MQDVGpHZrpe3Uy26zJBf/a8h0FZY6xJbthIMm8myH2Q= +github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A= +github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ= github.com/blevesearch/vellum v1.0.9 h1:PL+NWVk3dDGPCV0hoDu9XLLJgqU4E5s/dOeEJByQ2uQ= github.com/blevesearch/vellum v1.0.9/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k= +github.com/blevesearch/zap/v11 v11.0.14/go.mod h1:MUEZh6VHGXv1PKx3WnCbdP404LGG2IZVa/L66pyFwnY= +github.com/blevesearch/zap/v12 v12.0.14/go.mod h1:rOnuZOiMKPQj18AEKEHJxuI14236tTQ1ZJz4PAnWlUg= +github.com/blevesearch/zap/v13 v13.0.6/go.mod h1:L89gsjdRKGyGrRN6nCpIScCvvkyxvmeDCwZRcjjPCrw= +github.com/blevesearch/zap/v14 v14.0.5/go.mod h1:bWe8S7tRrSBTIaZ6cLRbgNH4TUDaC9LZSpRGs85AsGY= +github.com/blevesearch/zap/v15 v15.0.3/go.mod h1:iuwQrImsh1WjWJ0Ue2kBqY83a0rFtJTqfa9fp1rbVVU= github.com/blevesearch/zapx/v11 v11.3.7 h1:Y6yIAF/DVPiqZUA/jNgSLXmqewfzwHzuwfKyfdG+Xaw= github.com/blevesearch/zapx/v11 v11.3.7/go.mod h1:Xk9Z69AoAWIOvWudNDMlxJDqSYGf90LS0EfnaAIvXCA= github.com/blevesearch/zapx/v12 v12.3.7 h1:DfQ6rsmZfEK4PzzJJRXjiM6AObG02+HWvprlXQ1Y7eI= @@ -279,10 +328,11 @@ github.com/blevesearch/zapx/v13 v13.3.7 h1:igIQg5eKmjw168I7av0Vtwedf7kHnQro/M+ub github.com/blevesearch/zapx/v13 v13.3.7/go.mod h1:yyrB4kJ0OT75UPZwT/zS+Ru0/jYKorCOOSY5dBzAy+s= github.com/blevesearch/zapx/v14 v14.3.7 h1:gfe+fbWslDWP/evHLtp/GOvmNM3sw1BbqD7LhycBX20= github.com/blevesearch/zapx/v14 v14.3.7/go.mod h1:9J/RbOkqZ1KSjmkOes03AkETX7hrXT0sFMpWH4ewC4w= -github.com/blevesearch/zapx/v15 v15.3.7 h1:r8ZcNrlcMj2TmLlbNH16wZiL9reU0s7C2rAQKjFDtuE= -github.com/blevesearch/zapx/v15 v15.3.7/go.mod h1:m7Y6m8soYUvS7MjN9eKlz1xrLCcmqfFadmu7GhWIrLY= +github.com/blevesearch/zapx/v15 v15.3.8 h1:q4uMngBHzL1IIhRc8AJUEkj6dGOE3u1l3phLu7hq8uk= +github.com/blevesearch/zapx/v15 v15.3.8/go.mod h1:m7Y6m8soYUvS7MjN9eKlz1xrLCcmqfFadmu7GhWIrLY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= @@ -292,20 +342,24 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -316,6 +370,9 @@ github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -329,11 +386,15 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= @@ -361,6 +422,7 @@ github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -450,6 +512,10 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU= +github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k= +github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs= +github.com/couchbase/vellum v1.0.2/go.mod h1:FcwrEivFpNi24R3jLOs3n+fs5RnuQnQqCLBJ1uAg1W4= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 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/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -459,7 +525,10 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= @@ -468,10 +537,10 @@ github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpT github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= -github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -481,10 +550,12 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 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.10/go.mod h1:h5Enh0nG3Qbo9WjNFRrwmKUaePEBhXMOygbz3Ww7Sz0= +github.com/die-net/lrucache v0.0.0-20181227122439-19a39ef22a11/go.mod h1:ew0MSjCVDdtGMjF3kzLK9hwdgF5mOE8SbYVF3Rc7mkU= +github.com/disintegration/imaging v1.6.0/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= -github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= @@ -492,6 +563,7 @@ github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.13+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= @@ -503,21 +575,30 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g= -github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= +github.com/drone/envsubst v1.0.2 h1:dpYLMAspQHW0a8dZpLRKe9jCNvIGZPhCPrycZzIHdqo= +github.com/drone/envsubst v1.0.2/go.mod h1:bkZbnc/2vh1M12Ecn7EYScpI4YGYU0etwLJICOWi8Z0= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvyukov/go-fuzz v0.0.0-20210429054444-fca39067bc72/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= +github.com/dyatlov/go-opengraph v0.0.0-20210112100619-dae8665a5b09/go.mod h1:nYia/MIs9OyvXXYboPmNOj0gVWo97Wx0sde+ZuKkoM4= github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a h1:etIrTD8BQqzColk9nKRusM9um5+1q0iOEJLqfBMIK64= github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a/go.mod h1:emQhSYTXqB0xxjLITTw4EaWZ+8IIQYw+kx9GqNUKdLg= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -529,32 +610,39 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= 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/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= @@ -562,19 +650,28 @@ github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXt github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/getsentry/sentry-go v0.15.0 h1:CP9bmA7pralrVUedYZsmIHWpq/pBtXTSew7xvVpfLaA= -github.com/getsentry/sentry-go v0.15.0/go.mod h1:RZPJKSw+adu8PBNygiri/A98FqVr2HtRckJk9XVxJ9I= +github.com/getsentry/sentry-go v0.11.0/go.mod h1:KBQIxiZAetw62Cj8Ri964vAEWVdgfaUCn30Q3bCvANo= +github.com/getsentry/sentry-go v0.16.0 h1:owk+S+5XcgJLlGR/3+3s6N4d+uKwqYvh/eS0AIMjPWo= +github.com/getsentry/sentry-go v0.16.0/go.mod h1:ZXCloQLj0pG7mja5NK6NPf2V4A88YJ4pNlc2mOHwh6Y= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573 h1:u8AQ9bPa9oC+8/A/jlWouakhIvkFfuxgIIRjiy8av7I= github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573/go.mod h1:eBvb3i++NHDH4Ugo9qCvMw8t0mTSctaEa5blJbWcNxs= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-asn1-ber/asn1-ber v1.3.2-0.20191121212151-29be175fc3a3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-asn1-ber/asn1-ber v1.5.3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-chi/chi/v5 v5.0.2/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -588,6 +685,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -602,7 +700,7 @@ github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -621,17 +719,20 @@ github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvSc github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= +github.com/go-redis/redis/v8 v8.0.0/go.mod h1:isLoQT/NFSP7V67lyvM9GmdvLdyZ7pEhsXvvyQtnQTo= +github.com/go-redis/redis/v8 v8.10.0/go.mod h1:vXLTvigok0VtUX0znvbcEW1SOt4OA9CU1ZfnOtKOaiM= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.0.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU= +github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= @@ -659,11 +760,10 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= -github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/gocql/gocql v0.0.0-20210515062232-b7ef815b4556/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= @@ -674,9 +774,11 @@ github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gofiber/fiber/v2 v2.1.0/go.mod h1:aG+lMkwy3LyVit4CnmYUbUdgjpc3UYOltvlJZ78rgQ0= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -684,6 +786,7 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-migrate/migrate/v4 v4.14.1/go.mod h1:l7Ks0Au6fYHuUIxUhQ0rcVX1uLlJg54C/VvW7tvxSz0= github.com/golang-migrate/migrate/v4 v4.15.2 h1:vU+M05vs6jWHKDdmE1Ecwj0BznygFc4QsdRe2E/L7kc= github.com/golang-migrate/migrate/v4 v4.15.2/go.mod h1:f2toGLkYqD3JH+Todi4aZ2ZdbeUNx4sIwiOK96rE9Lw= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -730,15 +833,19 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -759,6 +866,7 @@ github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYV github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -784,6 +892,7 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -799,21 +908,26 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e h1:XmA6L9IPRdUr28a+SK/oMchGgQy159wvzXA5tJ7l+40= +github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e/go.mod h1:AFIo+02s+12CEg8Gzz9kzhCbmbq6JcKNrhHffCGA9z4= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20220221023154-0b2280d3ff96/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= +github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20210621113107-84c6004145de/go.mod h1:MtKwTfDNYAP5EtbQSMYjTSqvj1aXJKQRASWq3bwaP+g= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -823,50 +937,70 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gotestyourself/gotestyourself v1.4.0/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/graph-gophers/dataloader/v6 v6.0.0 h1:qBpmq3B8PIQesoh0EJXKGfw+ulMUb+KFl4IZOe9ScWg= github.com/graph-gophers/dataloader/v6 v6.0.0/go.mod h1:J15OZSnOoZgMkijpbZcwCmglIDYqlUiTEE1xLPbyqZM= -github.com/graph-gophers/graphql-go v1.4.0 h1:JE9wveRTSXwJyjdRd6bOQ7Ob5bewTUQ58Jv4OiVdpdE= -github.com/graph-gophers/graphql-go v1.4.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a h1:i0+Se9S+2zL5CBxJouqn2Ej6UQMwH1c57ZB6DVnqck4= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-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.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b/go.mod h1:VzxiSdG6j1pi7rwGm/xYI5RbtpBgM8sARDXlvEvxlu0= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 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-getter v1.6.2 h1:7jX7xcB+uVCliddZgeKyNxv0xoT7qL5KDtH7rU4IqIk= -github.com/hashicorp/go-getter v1.6.2/go.mod h1:IZCrswsZPeWv9IkVnLElzRU/gz/QPi6pZHn4tv6vbwA= -github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo= -github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-getter v1.5.5 h1:kAiuyk4LvTCqXfDkxNcCS/s0j/jye9USXT+iHH3EX68= +github.com/hashicorp/go-getter v1.5.5/go.mod h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI= +github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +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 v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA= -github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.2/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -882,13 +1016,21 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.2.4/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= +github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/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/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo= +github.com/ikawaha/kagome.ipadic v1.1.2/go.mod h1:DPSBbU0czaJhAb/5uKQZHMc9MTVRpDugJfX+HddPHHg= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -896,13 +1038,16 @@ github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/httpexpect/v2 v2.3.1/go.mod h1:ICTf89VBKSD3KB0fsyyHviKF8G8hyepP0dOXJPWz3T0= -github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE= -github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -911,6 +1056,7 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.3.2/go.mod h1:LvCquS3HbBKwgl7KbX9KyqEIumJAbm1UMcTvGaIf3bM= github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= @@ -948,12 +1094,14 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jamiealquiza/envy v1.1.0/go.mod h1:MP36BriGCLwEHhi1OU8E9569JNZrjWfCvzG7RsPnHus= github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba h1:QFQpJdgbON7I0jr2hYW7Bs+XV0qjc3d5tZoDnRFnqTg= github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= +github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -963,19 +1111,22 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 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/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v0.0.0-20171115153421-f7279a603ede/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -993,15 +1144,13 @@ github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3t github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kataras/blocks v0.0.5/go.mod h1:kcJIuvuA8QmGKFLHIZHdCAPCjcE85IhttzXd6W+ayfE= -github.com/kataras/golog v0.1.7/go.mod h1:jOSQ+C5fUqsNSwurB/oAHq1IFSb0KI3l6GMa7xB6dZA= -github.com/kataras/iris/v12 v12.2.0-alpha9/go.mod h1:JauDW3/DmvyLJW9oIJ84skBlwCJQaUgz6XP8ga1o+F0= -github.com/kataras/jwt v0.1.2/go.mod h1:4ss3aGJi58q3YGmhLUiOvNJnL7UlTXD7+Wf+skgsTmQ= -github.com/kataras/neffos v0.0.19/go.mod h1:CAAuFqHYX5t0//LLMiVWooOSp5FPeBRD8cn/892P1JE= -github.com/kataras/pio v0.0.10/go.mod h1:gS3ui9xSD+lAUpbYnjOGiQyY7sUMJO+EHpiRzhtZ5no= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/golog v0.0.18/go.mod h1:jRYl7dFYqP8aQj9VkwdBUXYZSfUktm+YYg1arJILfyw= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/pio v0.0.8/go.mod h1:NFfMp2kVP1rmV4N6gH6qgWpuoDKlrOeYi3VrAIWCGsE= github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= -github.com/kataras/tunnel v0.0.3/go.mod h1:VOlCoaUE5zN1buE+yAjWCkjfQ9hxGuhomKLsjei/5Zs= -github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -1009,28 +1158,34 @@ 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.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc= +github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI= -github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= 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= @@ -1039,8 +1194,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= @@ -1049,12 +1203,14 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4= +github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/ledongthuc/pdf v0.0.0-20210621053716-e28cb8259002/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= @@ -1065,16 +1221,19 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 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/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -1085,20 +1244,30 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= +github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37 h1:yK5Pb2R0PwS/RU4b4RbJjTj9xclZHJ064JFkZdAoHLY= +github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37/go.mod h1:h1HQ8UVoNMyDHzjPD7UtYbTPMWjP6d1qJZuLdT6ElNg= +github.com/mattermost/go-i18n v1.11.0/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG1cHc4Cz5ef9n3XVCxRWpAKUtqg9PJl5+y8= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= +github.com/mattermost/gorp v1.6.2-0.20210714143452-8b50f5209a7f/go.mod h1:QCQ3U0M9T/BlAdjKFJo0I1oe/YAgbyjNdhU8bpOLafk= +github.com/mattermost/gosaml2 v0.3.3/go.mod h1:Z429EIOiEi9kbq6yHoApfzlcXpa6dzRDc6pO+Vy2Ksk= github.com/mattermost/gziphandler v0.0.1 h1:uXHcXF5agnQ6bXabvpiwwwZOlCYoa7mKHH0lxns/o8w= github.com/mattermost/gziphandler v0.0.1/go.mod h1:CvvZR7sXqhj81V2swXuQY7T04Ccc89u7W7pHNPKev8g= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ0KNm4yZxxFvC1nvRz/gY/Daa35aI= github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ= -github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew= -github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg= +github.com/mattermost/logr v1.0.13/go.mod h1:Mt4DPu1NXMe6JxPdwCC0XBoxXmN9eXOIRPoZarU2PXs= +github.com/mattermost/logr/v2 v2.0.10/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg= +github.com/mattermost/logr/v2 v2.0.16 h1:jnePX4cPskC3WDFvUardh/xZfxNdsFXbEERJQ1kUEDE= +github.com/mattermost/logr/v2 v2.0.16/go.mod h1:1dm/YhTpozsqANXxo5Pi5zYLBsal2xY0pX+JZNbzYJY= github.com/mattermost/mattermost-plugin-api v0.1.1 h1:bNnPbWCLWZpT/k2kjUxNnzCfUggU8WKs2ddz7hNjg1U= github.com/mattermost/mattermost-plugin-api v0.1.1/go.mod h1:9yZhtg0bBj3kqSTjXnjYBMZoTsWbe3ajdFMdl9/Jz34= -github.com/mattermost/mattermost-server/v6 v6.0.0-20230113170349-ea08d47f6051 h1:bL3nQUUQmQotteHuA6ltKga3S3PbR03ElM5qJRXSeyY= -github.com/mattermost/mattermost-server/v6 v6.0.0-20230113170349-ea08d47f6051/go.mod h1:U3gSM0I15WSMHPpDEU30mmc4JrbSDk+8F1+MFLOHWD0= +github.com/mattermost/mattermost-plugin-playbooks/client v0.7.0 h1:5TPlzBmrrl6/q6rupBzGvLgeJf/qsn1NoqQmuPDJvdw= +github.com/mattermost/mattermost-plugin-playbooks/client v0.7.0/go.mod h1:pIR9gutNcE4K726viIya01XT7+T9ziLF0jd5ho6kJlM= +github.com/mattermost/mattermost-server/v6 v6.0.0-20210825182941-ddfa6e2436d6/go.mod h1:+S8CsNEPv1FOl1usaPBQ6Gu9+Sm1Cc9YdU/Qh1YMGVI= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230205103718-6d8da29d69e6 h1:ahK9ys8C+/QigrRpOilQqPlbi2uIRsCt/LnqHf93PJQ= +github.com/mattermost/mattermost-server/v6 v6.0.0-20230205103718-6d8da29d69e6/go.mod h1:o61MGMh7We01wGr1ydGDA5mmNpjTzaBVWUAlezsgx50= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e h1:VfNz+fvJ3DxOlALM22Eea8ONp5jHrybKBCcCtDPVlss= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e/go.mod h1:xo0ljDknTpPxEdhhrUdwhLCexIsYyDKS6b41HqG8wGU= github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 h1:G9tL6JXRBMzjuD1kkBtcnd42kUiT6QDwxfFYu7adM6o= @@ -1108,6 +1277,7 @@ github.com/mattermost/squirrel v0.2.0/go.mod h1:NPPtk+CdpWre4GxMGoOpzEVFVc0ZoEFy 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= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -1122,43 +1292,56 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= 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.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= -github.com/mediocregopher/radix/v3 v3.8.0/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/microcosm-cc/bluemonday v1.0.18/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/microcosm-cc/bluemonday v1.0.16/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM= github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg= github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.43 h1:14Q4lwblqTdlAmba05oq5xL0VBLHi06zS4yLnIkz6hI= -github.com/minio/minio-go/v7 v7.0.43/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/minio-go/v7 v7.0.11/go.mod h1:WoyW+ySKAKjY98B9+7ZbI8z8S3jaxaisdcvj9TGlazA= +github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs= +github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= @@ -1166,15 +1349,16 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= @@ -1196,9 +1380,13 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= +github.com/muesli/smartcrop v0.2.1-0.20181030220600-548bbf0c0965/go.mod h1:i2fCI/UorTfgEpPPLWiFBv4pye+YAG78RwcQLUkocpI= +github.com/muesli/smartcrop v0.3.0/go.mod h1:i2fCI/UorTfgEpPPLWiFBv4pye+YAG78RwcQLUkocpI= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY= @@ -1206,19 +1394,31 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= -github.com/nats-io/jwt/v2 v2.2.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= -github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= -github.com/nats-io/nats-server/v2 v2.7.3/go.mod h1:eJUrA5gm0ch6sJTEv85xmXIgQWsB0OyjkTsKXvlHbYc= -github.com/nats-io/nats.go v1.13.1-0.20220121202836-972a071d373d/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= -github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= +github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnlBDugfR4Gg/8uHU= +github.com/nats-io/nats-streaming-server v0.20.0/go.mod h1:yJjUp4TmfYqllCtctAQ6Kz6ZRy5kaLgqHvuU1TGSrCw= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nats-io/stan.go v0.8.1/go.mod h1:Ci6mUIpGQTjl++MqK2XzkWI/0vF+Bl72uScx7ejSYmU= +github.com/nats-io/stan.go v0.8.2/go.mod h1:Ejm8bbHnMTSptU6uNMAVuxeapMJYBB/Ml3ej6z4GoSY= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= -github.com/nicksnyder/go-i18n/v2 v2.2.1 h1:aOzRCdwsJuoExfZhoiXHy4bjruwCMdt5otbYojM/PaA= -github.com/nicksnyder/go-i18n/v2 v2.2.1/go.mod h1:fF2++lPHlo+/kPaj3nB0uxtPwzlPm+BlgwGX7MkeGj0= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/ngdinhtoan/glide-cleanup v0.2.0/go.mod h1:UQzsmiDOb8YV3nOsCxK/c9zPpCZVNoHScRE3EO9pVMM= +github.com/nicksnyder/go-i18n/v2 v2.2.0 h1:MNXbyPvd141JJqlU6gJKrczThxJy+kdCNivxZpBQFkw= +github.com/nicksnyder/go-i18n/v2 v2.2.0/go.mod h1:4OtLfzqyAxsscyCb//3gfqSvBc81gImX91LrZzczN1o= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= @@ -1226,6 +1426,8 @@ github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWk github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -1234,9 +1436,11 @@ github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:v github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/olivere/elastic v6.2.35+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1245,25 +1449,31 @@ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/oov/psd v0.0.0-20210618170533-9fb823ddb631/go.mod h1:GHI1bnmAcbp96z6LNfBJvtrjxhaXGkbsk967utPlvL8= github.com/oov/psd v0.0.0-20220121172623-5db5eafcecbb h1:JF9kOhBBk4WPF7luXFu5yR+WgaFm9L/KiHJHhU9vDwA= github.com/oov/psd v0.0.0-20220121172623-5db5eafcecbb/go.mod h1:GHI1bnmAcbp96z6LNfBJvtrjxhaXGkbsk967utPlvL8= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1291,22 +1501,39 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/openfaas/faas-cli v0.0.0-20230119133646-fea2bf5a6d0c h1:bKdpxt1nwx1gORMakzuqQ5M6iDeowMxBAXQGGmBMZks= -github.com/openfaas/faas-cli v0.0.0-20230119133646-fea2bf5a6d0c/go.mod h1:4Q1Cp5H5OhMPFkXz+rLn9+FNPlh0zWSixaWEEjkAwY4= +github.com/openfaas/faas-cli v0.0.0-20210705110531-a230119be00f h1:QhxeEkMD2HaHHrMRfn1gpyTw06ieNHmh55u3WIB1YMc= +github.com/openfaas/faas-cli v0.0.0-20210705110531-a230119be00f/go.mod h1:3gVq4xaCOfkCc0KpEUzasfsRDkbZwa6T99G1PmTJsyw= +github.com/openfaas/faas-provider v0.17.3/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98= +github.com/openfaas/faas-provider v0.18.5/go.mod h1:fq1JL0mX4rNvVVvRLaLRJ3H6o667sHuyP5p/7SZEe98= +github.com/openfaas/faas/gateway v0.0.0-20210311210633-a6dbb4cd0285/go.mod h1:ZZUyq1Ghd3zvhKvSWfXelAsvbUxWP1TqWtvapP4701Q= +github.com/openfaas/nats-queue-worker v0.0.0-20200512211843-8e9eefd5a320/go.mod h1:BfT8MB890hbhbtPid+X/oU0HAznGFS581NiG2hkr8Rc= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/gosseract/v2 v2.2.4/go.mod h1:ahOp/kHojnOMGv1RaUnR0jwY5JVa6BYKhYAS8nbMLSo= +github.com/otiai10/gosseract/v2 v2.3.1/go.mod h1:2ZOGgdTIXQzCS5f+N1HkcXRgDX6K3ZoYe3Yvo++cpp4= github.com/otiai10/gosseract/v2 v2.4.0 h1:gYd3mx6FuMtIlxL4sYb9JLCFEDzg09VgNSZRNbqpiGM= github.com/otiai10/gosseract/v2 v2.4.0/go.mod h1:fhbIDRh29bj13vni6RT3gtWKjKCAeqDYI4C1dxeJuek= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI= github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -1315,56 +1542,78 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterbourgon/diskv v0.0.0-20171120014656-2973218375c3/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -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.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 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= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1373,14 +1622,18 @@ github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/reflog/dateconstraints v0.2.1 h1:Hz1n2Q1vEm0Rj5gciDQcCN1iPBwfFjxUJy32NknGP/s= github.com/reflog/dateconstraints v0.2.1/go.mod h1:Ax8AxTBcJc3E/oVS2hd2j7RDM/5MDtuPwuR7lIHtPLo= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa h1:tEkEyxYeZ43TR55QU/hsIt9aRGBxbgGuz9CGykjvogY= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= @@ -1391,22 +1644,26 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= -github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= +github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/rudderlabs/analytics-go v3.3.1+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30= github.com/rudderlabs/analytics-go v3.3.3+incompatible h1:OG0XlKoXfr539e2t1dXtTB+Gr89uFW+OUNQBVhHIIBY= github.com/rudderlabs/analytics-go v3.3.3+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30= +github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1414,10 +1671,13 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= @@ -1426,11 +1686,11 @@ github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N++y4= github.com/segmentio/backo-go v1.0.1/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -1473,34 +1733,32 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/assertions v1.2.1/go.mod h1:wDmR7qL282YbGsPy6H/yAsesrxfxaaSlJazyFLYVFx8= +github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= +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/snowflakedb/gosnowflake v1.6.3/go.mod h1:6hLajn6yxuJ4xUHZegMekpq9rnQbGJ7TMwXjgTmA6lg= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -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 v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1510,26 +1768,35 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 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/splitio/go-client/v6 v6.1.0/go.mod h1:CEGAEFT99Fwb32ZIRcnZoXTMXddtB6IIpTmt3RP8mnM= github.com/splitio/go-client/v6 v6.2.1 h1:EH3xYH7fr2c0I0ZtYvsyn7DjC9ZmoNAFLoKoT3BmQFU= github.com/splitio/go-client/v6 v6.2.1/go.mod h1:+HnGMevmSUk56va2egs9W2s9mJ7LW9IXiDPB1ExOi+k= +github.com/splitio/go-split-commons/v3 v3.1.0/go.mod h1:29NCy20oAS4ZMy4qkwTd6277eieVDonx4V/aeDU/wUQ= github.com/splitio/go-split-commons/v4 v4.2.0/go.mod h1:mzanM00PV8t1FL6IHc2UXepIH2z79d49ArZ2LoJHGrY= -github.com/splitio/go-split-commons/v4 v4.2.2 h1:p4Gq4+Wxto+f+7g4AoxmMON1jkOU8abqAIV1pb8ke9M= -github.com/splitio/go-split-commons/v4 v4.2.2/go.mod h1:mzanM00PV8t1FL6IHc2UXepIH2z79d49ArZ2LoJHGrY= +github.com/splitio/go-split-commons/v4 v4.2.3 h1:/bQg8Z0eCkF9RHl7Dh1SJ8j7Ci024bgtkZEWwEKXywc= +github.com/splitio/go-split-commons/v4 v4.2.3/go.mod h1:mzanM00PV8t1FL6IHc2UXepIH2z79d49ArZ2LoJHGrY= +github.com/splitio/go-toolkit/v4 v4.2.0/go.mod h1:EdIHN0yzB1GTXDYQc0KdKvnjkO/jfUM2YqHVYfhD3Wo= github.com/splitio/go-toolkit/v5 v5.2.2 h1:VHSJoIH9tsRt2cCzGKN4WG3BoGCr0tCPZIl8APtJ4bw= github.com/splitio/go-toolkit/v5 v5.2.2/go.mod h1:SYi/svhhtEgdMSb5tNcDcMjOSUH/7XVkvjp5dPL+nBE= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc= +github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7Z4dM9/Y= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1545,33 +1812,38 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69 github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tdewolff/minify/v2 v2.10.0/go.mod h1:6XAjcHM46pFcRE0eztigFPm0Q+Cxsw8YhEWT+rDkcZM= -github.com/tdewolff/minify/v2 v2.11.10/go.mod h1:dHOS3dk+nJ0M3q3uM3VlNzTb70cou+ov0ki7C4PAFgM= -github.com/tdewolff/parse/v2 v2.5.27/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho= -github.com/tdewolff/parse/v2 v2.6.0/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho= -github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tebeka/snowball v0.4.2/go.mod h1:4IfL14h1lvwZcp1sfXuuc7/7yCsvVffTWxWxCLfFpYg= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/throttled/throttled v2.2.5+incompatible h1:65UB52X0qNTYiT0Sohp8qLYVFwZQPDw85uSa65OljjQ= github.com/throttled/throttled v2.2.5+incompatible/go.mod h1:0BjlrEGQmvxps+HuXLsyRdqpSRvJpq0PNIsOtqP9Nos= -github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= -github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= +github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= -github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= -github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/tylerb/graceful v1.2.15/go.mod h1:LPYTbOYmUTdabwRt0TGhLllQ0MUNbs0Y5q1WXJOI9II= +github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= @@ -1580,10 +1852,13 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -1591,6 +1866,7 @@ github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= @@ -1607,21 +1883,27 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/wiggin77/cfg v1.0.2/go.mod h1:b3gotba2e5bXTqTW48DwIFoLc+4lWKP7WPi/CdvZ4aE= github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg= +github.com/wiggin77/merror v1.0.3/go.mod h1:H2ETSu7/bPE0Ymf4bEwdUoo73OOEkdClnoRisfw0Nm0= github.com/wiggin77/merror v1.0.4 h1:XxFLEevmQQfgJW2AxhapuMG7C1fQqfbim/XyUmYv/ZM= github.com/wiggin77/merror v1.0.4/go.mod h1:H2ETSu7/bPE0Ymf4bEwdUoo73OOEkdClnoRisfw0Nm0= github.com/wiggin77/srslog v1.0.1 h1:gA2XjSMy3DrRdX9UqLuDtuVAAshb8bE1NhX1YK0Qe+8= github.com/wiggin77/srslog v1.0.1/go.mod h1:fehkyYDq1QfuYn60TDPu9YdY2bB85VUW2mvN1WynEls= +github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= @@ -1633,7 +1915,6 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -1643,20 +1924,22 @@ 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.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.3 h1:3HUJmBFbQW9fhQOzMgseU134xfi6hU+mjWywx5Ty+/M= github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= 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= @@ -1665,22 +1948,30 @@ go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lL go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.7.0/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= +go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/otel v0.11.0/go.mod h1:G8UCk+KooF2HLkgo8RHX9epABH/aRGYET7gQOqBVdB0= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= @@ -1688,27 +1979,34 @@ go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= +go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 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/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= @@ -1716,11 +2014,12 @@ go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95a 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.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/build v0.0.0-20190314133821-5284462c4bec/go.mod h1:atTaCNAy0f16Ah5aV1gMSwgiKVHwu/JncqDpuRr7lS4= 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-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1738,22 +2037,24 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1770,8 +2071,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200908183739-ae8ad444f925/go.mod h1:1phAWC201xIgDyaFpmDeZkgf70Q4Pd/CNqfRtVPtxNw= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1780,10 +2083,12 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk= -golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= +golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.3.0 h1:HTDXbdK9bjfSWkPzDJIw89W8CAtfFGduujWs33NLLsg= +golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1803,6 +2108,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -1811,6 +2117,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180530234432-1e491301e022/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= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1823,6 +2130,7 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1840,6 +2148,7 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1857,9 +2166,12 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 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-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1885,9 +2197,9 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1896,6 +2208,7 @@ golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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= @@ -1905,14 +2218,13 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ 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-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1938,8 +2250,10 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1952,6 +2266,7 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1966,8 +2281,11 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/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-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1975,6 +2293,7 @@ golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2011,19 +2330,21 @@ golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/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-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/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= @@ -2044,7 +2365,6 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/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-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2064,17 +2384,15 @@ golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2083,6 +2401,7 @@ golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2093,6 +2412,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2103,9 +2423,7 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2113,16 +2431,20 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -2136,6 +2458,7 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2150,6 +2473,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -2170,9 +2494,14 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200806022845-90696ccdc692/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200814230902-9882f1d1823d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +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-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -2188,8 +2517,9 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= 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= @@ -2207,7 +2537,10 @@ gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -2229,7 +2562,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q 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/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -2242,8 +2574,8 @@ google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3h google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2256,16 +2588,20 @@ google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190321212433-e79c0c59cdb5/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -2293,9 +2629,13 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +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-20201019141844-1ed22bb0c154/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-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2333,16 +2673,20 @@ google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 h1:jCw9YRd2s40X9Vxi4zKsPRvSPlHWNqadVkpbMsCPzPQ= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf h1:/JqRexUvugu6JURQ0O7RfV1EnvgrOxUV4tSjuAv0Sr0= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= @@ -2355,6 +2699,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji 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.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= @@ -2372,8 +2717,8 @@ google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5 google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= 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= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2400,33 +2745,38 @@ gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= 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.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/olivere/elastic.v6 v6.2.35/go.mod h1:2cTT8Z+/LcArSWpCgvZqBgt3VOqXiy7v00w12Lz8bd4= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -2438,6 +2788,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -2446,12 +2797,14 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg= gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= +gotest.tools v1.4.0/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2502,18 +2855,21 @@ k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= -modernc.org/cc/v3 v3.36.0 h1:0kmRkTmqNidmu3c7BNDSdVHCxXCkWLmWmCIVX4LUboo= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6 h1:3l18poV+iUemQ98O3X5OMr97LOqlzis+ytivU4NqGhA= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= @@ -2528,38 +2884,44 @@ modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWC modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.7 h1:qzQtHhsZNpVPpeCu+aMIQldXeV1P0vRhSqCL0nOIJOA= modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= -modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= -modernc.org/sqlite v1.18.0 h1:ef66qJSgKeyLyrF4kQ2RHw/Ue3V89fyFNbGL073aDjI= modernc.org/sqlite v1.18.0/go.mod h1:B9fRWZacNxJBHoCJZQr1R54zhVn3fjfl0aszflrTSxY= +modernc.org/sqlite v1.20.1 h1:z6qRLw72B0VfRrJjs3l6hWkzYDx1bo0WGVrBGP4ohhM= +modernc.org/sqlite v1.20.1/go.mod h1:fODt+bFmc/j8LcoCbMSkAuKuGmhxjG45KGc25N2705M= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= -modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= -modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= -moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= @@ -2573,5 +2935,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +willnorris.com/go/gifresize v1.0.0/go.mod h1:eBM8gogBGCcaH603vxSpnfjwXIpq6nmnj/jauBDKtAk= +willnorris.com/go/imageproxy v0.10.0/go.mod h1:2tWdKRneln3E9X/zwH1RINpQAQWPeUiNynZ7UQ9OROk= diff --git a/server/appservices/kv.go b/server/appservices/kv.go index 04afed2ff..e2fd65d6c 100644 --- a/server/appservices/kv.go +++ b/server/appservices/kv.go @@ -70,11 +70,11 @@ func (a *AppServices) KVList(r *incoming.Request, prefix string, processf func(k } func (a *AppServices) KVDebugInfo(r *incoming.Request) (*store.KVDebugInfo, error) { - return a.store.GetDebugKVInfo(r.Log) + return store.GetKVDebugInfo(r) } func (a *AppServices) KVDebugAppInfo(r *incoming.Request, appID apps.AppID) (*store.KVDebugAppInfo, error) { - info, err := a.store.GetDebugKVInfo(r.Log) + info, err := store.GetKVDebugInfo(r) if err != nil { return nil, err } diff --git a/server/appservices/oauth2.go b/server/appservices/oauth2.go index 6c3738022..23b1cbe18 100644 --- a/server/appservices/oauth2.go +++ b/server/appservices/oauth2.go @@ -50,7 +50,6 @@ func (a *AppServices) StoreOAuth2App(r *incoming.Request, data []byte) error { } r.API.Mattermost.Frontend.PublishWebSocketEvent(config.WebSocketEventRefreshBindings, map[string]interface{}{}, &model.WebsocketBroadcast{}) - return nil } @@ -66,9 +65,7 @@ func (a *AppServices) StoreOAuth2User(r *incoming.Request, data []byte) error { return utils.NewInvalidError("payload is not valid JSON") } - appID := r.SourceAppID() - actingUserID := r.ActingUserID() - app, err := a.store.App.Get(appID) + app, err := a.store.App.Get(r.SourceAppID()) if err != nil { return err } @@ -76,7 +73,7 @@ func (a *AppServices) StoreOAuth2User(r *incoming.Request, data []byte) error { return utils.NewUnauthorizedError("%s is not authorized to use remote OAuth2", app.AppID) } - oldData, err := a.store.OAuth2.GetUser(appID, actingUserID) + oldData, err := a.store.OAuth2.GetUser(r) if err != nil { return err } @@ -84,12 +81,12 @@ func (a *AppServices) StoreOAuth2User(r *incoming.Request, data []byte) error { return nil } - err = a.store.OAuth2.SaveUser(appID, actingUserID, data) + err = a.store.OAuth2.SaveUser(r, data) if err != nil { return err } - r.API.Mattermost.Frontend.PublishWebSocketEvent(config.WebSocketEventRefreshBindings, map[string]interface{}{}, &model.WebsocketBroadcast{UserId: actingUserID}) + r.API.Mattermost.Frontend.PublishWebSocketEvent(config.WebSocketEventRefreshBindings, map[string]interface{}{}, &model.WebsocketBroadcast{UserId: r.ActingUserID()}) return nil } @@ -104,9 +101,7 @@ func (a *AppServices) GetOAuth2User(r *incoming.Request) ([]byte, error) { return nil, err } - appID := r.SourceAppID() - actingUserID := r.ActingUserID() - app, err := a.store.App.Get(appID) + app, err := a.store.App.Get(r.SourceAppID()) if err != nil { return nil, err } @@ -114,7 +109,7 @@ func (a *AppServices) GetOAuth2User(r *incoming.Request) ([]byte, error) { return nil, utils.NewUnauthorizedError("%s is not authorized to use remote OAuth2", app.AppID) } - data, err := a.store.OAuth2.GetUser(appID, actingUserID) + data, err := a.store.OAuth2.GetUser(r) if err != nil && !errors.Is(err, utils.ErrNotFound) { return nil, err } diff --git a/server/appservices/service.go b/server/appservices/service.go index 194accff7..7d08e7c5b 100644 --- a/server/appservices/service.go +++ b/server/appservices/service.go @@ -15,7 +15,6 @@ type Service interface { Subscribe(*incoming.Request, apps.Subscription) error GetSubscriptions(*incoming.Request) ([]apps.Subscription, error) Unsubscribe(*incoming.Request, apps.Event) error - UnsubscribeApp(*incoming.Request, apps.AppID) error // KV @@ -31,6 +30,10 @@ type Service interface { StoreOAuth2App(_ *incoming.Request, data []byte) error StoreOAuth2User(_ *incoming.Request, data []byte) error GetOAuth2User(_ *incoming.Request) ([]byte, error) + + // Internal + + DeleteAppData(r *incoming.Request, appID apps.AppID, force bool) error } type AppServices struct { @@ -44,3 +47,29 @@ func NewService(store *store.Service) *AppServices { store: store, } } + +func (a *AppServices) DeleteAppData(r *incoming.Request, appID apps.AppID, force bool) (err error) { + defer func() { + if err != nil { + r.Log.WithError(err).Errorf("Failed to clean up app data for %s: %v", appID, err) + } + }() + + if err = r.Check( + r.RequireActingUser, + r.RequireSysadminOrPlugin, + ); err != nil { + return err + } + + // Remove all KV and user data. + if err = store.RemoveAllKVAndUserDataForApp(r, appID); err != nil { + return err + } + + // Remove all subscriptions. + if err = a.unsubscribeApp(r, appID); err != nil { + return err + } + return nil +} diff --git a/server/appservices/subscriptions.go b/server/appservices/subscriptions.go index e13de79d8..26bfabdd6 100644 --- a/server/appservices/subscriptions.go +++ b/server/appservices/subscriptions.go @@ -44,7 +44,7 @@ func (a *AppServices) Subscribe(r *incoming.Request, sub apps.Subscription) erro AppID: r.SourceAppID(), OwnerUserID: ownerID, }) - err = a.store.Subscription.Save(sub.Event, all) + err = a.store.Subscription.Put(r, sub.Event, &all) if err != nil { return err } @@ -80,16 +80,20 @@ func (a *AppServices) GetSubscriptions(r *incoming.Request) (out []apps.Subscrip return nil, err } - allStored, err := a.store.Subscription.List() + events, err := a.store.Subscription.ListSubscribedEvents(r) if err != nil { return nil, err } - - for _, stored := range allStored { - for _, s := range stored.Subscriptions { + for _, event := range events { + var subs []store.Subscription + subs, err = a.store.Subscription.Get(r, event) + if err != nil { + return nil, errors.Wrap(err, "failed to get subscriptions for "+event.String()) + } + for _, s := range subs { if s.AppID == r.SourceAppID() && s.OwnerUserID == r.ActingUserID() { out = append(out, apps.Subscription{ - Event: stored.Event, + Event: event, Call: s.Call, }) } @@ -99,7 +103,7 @@ func (a *AppServices) GetSubscriptions(r *incoming.Request) (out []apps.Subscrip return out, nil } -func (a *AppServices) UnsubscribeApp(r *incoming.Request, appID apps.AppID) error { +func (a *AppServices) unsubscribeApp(r *incoming.Request, appID apps.AppID) error { err := r.Check( r.RequireSysadminOrPlugin, ) @@ -107,23 +111,32 @@ func (a *AppServices) UnsubscribeApp(r *incoming.Request, appID apps.AppID) erro return err } - allStored, err := a.store.Subscription.List() + events, err := a.store.Subscription.ListSubscribedEvents(r) if err != nil { return err } n := 0 - for _, stored := range allStored { - modified := []store.Subscription{} - for _, s := range stored.Subscriptions { - if s.AppID == appID { + for _, event := range events { + var subs []store.Subscription + modified := store.Subscriptions{} + subs, err = a.store.Subscription.Get(r, event) + if err != nil { + return errors.Wrap(err, "failed to get subscriptions for "+event.String()) + } + for _, sub := range subs { + if sub.AppID == appID { n++ } else { - modified = append(modified, s) + modified = append(modified, sub) } } - if len(modified) < len(stored.Subscriptions) { - err = a.store.Subscription.Save(stored.Event, modified) + if len(modified) < len(subs) { + if len(modified) > 0 { + err = a.store.Subscription.Put(r, event, &modified) + } else { + err = a.store.Subscription.Put(r, event, nil) + } if err != nil { return err } @@ -134,8 +147,8 @@ func (a *AppServices) UnsubscribeApp(r *incoming.Request, appID apps.AppID) erro return err } -func (a *AppServices) unsubscribe(r *incoming.Request, ownerUserID string, e apps.Event) ([]store.Subscription, error) { - all, err := a.store.Subscription.Get(e) +func (a *AppServices) unsubscribe(r *incoming.Request, ownerUserID string, event apps.Event) (store.Subscriptions, error) { + all, err := a.store.Subscription.Get(r, event) if err != nil { return nil, err } @@ -159,14 +172,19 @@ func (a *AppServices) unsubscribe(r *incoming.Request, ownerUserID string, e app if i < len(all) { modified = append(modified, all[i+1:]...) } - err = a.store.Subscription.Save(e, modified) + newList := &modified + if len(modified) == 0 { + newList = nil + } + err = a.store.Subscription.Put(r, event, newList) if err != nil { return nil, err } + return modified, nil } - return all, errors.Wrap(utils.ErrNotFound, "You are not subscribed to this notification") + return all, errors.Wrapf(utils.ErrNotFound, "failed to get subscriptions for event %s", event.String()) } func (a *AppServices) hasPermissionToSubscribe(r *incoming.Request, sub apps.Subscription) func() error { diff --git a/server/builtin/debug_kv_create.go b/server/builtin/debug_kv_create.go index 8de47c038..6e8a44034 100644 --- a/server/builtin/debug_kv_create.go +++ b/server/builtin/debug_kv_create.go @@ -59,7 +59,7 @@ func (a *builtinApp) debugKVCreate(r *incoming.Request, creq apps.CallRequest) a } key := "" - key, err = store.Hashkey(store.KVAppPrefix, appID, creq.Context.ActingUser.Id, namespace, id) + key, err = store.Hashkey(store.KVPrefix, appID, creq.Context.ActingUser.Id, namespace, id) if err != nil { return apps.NewErrorResponse(err) } diff --git a/server/builtin/debug_kv_edit.go b/server/builtin/debug_kv_edit.go index 2dc5b0b12..f38ad99c2 100644 --- a/server/builtin/debug_kv_edit.go +++ b/server/builtin/debug_kv_edit.go @@ -55,7 +55,7 @@ func (a *builtinApp) debugKVEdit(r *incoming.Request, creq apps.CallRequest) app key = string(decoded) } else { var err error - key, err = store.Hashkey(store.KVAppPrefix, appID, creq.Context.ActingUser.Id, namespace, id) + key, err = store.Hashkey(store.KVPrefix, appID, creq.Context.ActingUser.Id, namespace, id) if err != nil { return apps.NewErrorResponse(err) } diff --git a/server/builtin/debug_kv_info.go b/server/builtin/debug_kv_info.go index dd263d094..6e2b7bcd3 100644 --- a/server/builtin/debug_kv_info.go +++ b/server/builtin/debug_kv_info.go @@ -74,7 +74,7 @@ func (a *builtinApp) debugKVInfoForAll(r *incoming.Request, creq apps.CallReques message += fmt.Sprintf(" - `%s`: %v (%v kv, %v users, %v tokens)\n", appID, appInfo.Total(), appInfo.AppKVCount, appInfo.UserCount, appInfo.TokenCount) } - totalKnown := info.OAuth2StateCount + info.AppsTotal + info.Other + totalKnown := info.OAuth2StateCount + info.AppsTotal + info.Other + info.CachedStoreTotal if totalKnown != info.Total { message += fmt.Sprintf("- **UNKNOWN**: %v\n", info.Total-totalKnown) } diff --git a/server/builtin/debug_store_pollute.go b/server/builtin/debug_store_pollute.go index ae137c681..a50aa5b05 100644 --- a/server/builtin/debug_store_pollute.go +++ b/server/builtin/debug_store_pollute.go @@ -48,7 +48,7 @@ func (a *builtinApp) debugStorePollute(r *incoming.Request, creq apps.CallReques keys := []string{} for i := 0; i < c; i++ { - key := fmt.Sprintf("%s-%v-%d", store.KVDebugPrefix, time.Now().UnixMilli(), i) + key := fmt.Sprintf("%s-%v-%d", store.DebugPrefix, time.Now().UnixMilli(), i) _, err = a.api.Mattermost.KV.Set(key, []byte("garbage")) if err != nil { return apps.NewErrorResponse(err) diff --git a/server/config/config.go b/server/config/config.go index 445fa7b01..859d1a7d7 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -15,25 +15,11 @@ import ( // // StoredConfig should be abbreviated as sc. type StoredConfig struct { - // InstalledApps is a list of all apps installed on the Mattermost instance. - // - // For each installed app, an entry of string(AppID) -> sha1(App) is added, - // and the App struct is stored in KV under app_. Implementation - // in `store.App`. - InstalledApps map[string]string `json:"installed_apps,omitempty"` - - // LocalManifests is a list of locally-stored manifests. Local is in - // contrast to the "global" list of manifests which in the initial version - // is loaded from S3. - // - // For each installed app, an entry of string(AppID) -> sha1(Manifest) is - // added, and the Manifest struct is stored in KV under - // manifest_. Implementation in `store.Manifest`. - LocalManifests map[string]string `json:"local_manifests,omitempty"` - DeveloperModeOverride *bool `json:"developer_mode"` AllowHTTPAppsOverride *bool `json:"allow_http_apps"` + CachedStore string `json:"cache_store,omitempty"` + LogChannelID string `json:"log_channel_id,omitempty"` LogChannelLevel int `json:"log_channel_level,omitempty"` LogChannelJSON bool `json:"log_channel_json,omitempty"` diff --git a/server/config/service.go b/server/config/service.go index ae5a8c8d3..a0541a422 100644 --- a/server/config/service.go +++ b/server/config/service.go @@ -39,9 +39,11 @@ type Service interface { API() API NewBaseLogger() utils.Logger SystemDefaultFlags() (devMode, allowHTTPApps bool) + IsClusterLeader() bool Reconfigure(_ StoredConfig, verbose bool, _ ...Configurable) error StoreConfig(StoredConfig, utils.Logger) error + OnClusterLeaderChanged(isLeader bool) } var _ Service = (*service)(nil) @@ -54,6 +56,7 @@ type service struct { lock *sync.RWMutex conf *Config mattermostConfig *model.Config + isClusterLeader bool } func MakeService(api API, pliginManifest model.Manifest, botUserID string) (Service, error) { @@ -263,6 +266,23 @@ func (s *service) Reconfigure(newStoredConfig StoredConfig, verbose bool, servic return nil } +func (s *service) OnClusterLeaderChanged(isLeader bool) { + s.lock.Lock() + if s.conf != nil { + s.isClusterLeader = isLeader + } + s.lock.Unlock() + + s.NewBaseLogger().Debugf("Cluster leader changed to %t", isLeader) +} + +func (s *service) IsClusterLeader() bool { + s.lock.Lock() + defer s.lock.Unlock() + + return s.isClusterLeader +} + func (s *service) StoreConfig(sc StoredConfig, log utils.Logger) error { log.Debugf("Storing configuration: developer mode %t, allow http apps %t", sc.DeveloperModeOverride != nil && *sc.DeveloperModeOverride, diff --git a/server/config/test_service.go b/server/config/test_service.go index 0e21c872a..a74995d4d 100644 --- a/server/config/test_service.go +++ b/server/config/test_service.go @@ -71,5 +71,7 @@ func (s *TestService) StoreConfig(sc StoredConfig, _ utils.Logger) error { func (s *TestService) API() API { return s.api } func (s *TestService) Get() Config { return s.config } func (s *TestService) NewBaseLogger() utils.Logger { return s.log } +func (s *TestService) OnClusterLeaderChanged(bool) {} +func (s *TestService) IsClusterLeader() bool { return true } func (s *TestService) Reconfigure(StoredConfig, bool, ...Configurable) error { return nil } func (s *TestService) SystemDefaultFlags() (bool, bool) { return false, false } diff --git a/server/mocks/mock_store/mock_appstore.go b/server/mocks/mock_store/mock_app_store.go similarity index 51% rename from server/mocks/mock_store/mock_appstore.go rename to server/mocks/mock_store/mock_app_store.go index 33431e435..eeb6e109d 100644 --- a/server/mocks/mock_store/mock_appstore.go +++ b/server/mocks/mock_store/mock_app_store.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/mattermost/mattermost-plugin-apps/server/store (interfaces: AppStore) +// Source: github.com/mattermost/mattermost-plugin-apps/server/store (interfaces: Apps) // Package mock_store is a generated GoMock package. package mock_store @@ -11,34 +11,33 @@ import ( apps "github.com/mattermost/mattermost-plugin-apps/apps" incoming "github.com/mattermost/mattermost-plugin-apps/server/incoming" store "github.com/mattermost/mattermost-plugin-apps/server/store" - utils "github.com/mattermost/mattermost-plugin-apps/utils" ) -// MockAppStore is a mock of AppStore interface. -type MockAppStore struct { +// MockApps is a mock of Apps interface. +type MockApps struct { ctrl *gomock.Controller - recorder *MockAppStoreMockRecorder + recorder *MockAppsMockRecorder } -// MockAppStoreMockRecorder is the mock recorder for MockAppStore. -type MockAppStoreMockRecorder struct { - mock *MockAppStore +// MockAppsMockRecorder is the mock recorder for MockApps. +type MockAppsMockRecorder struct { + mock *MockApps } -// NewMockAppStore creates a new mock instance. -func NewMockAppStore(ctrl *gomock.Controller) *MockAppStore { - mock := &MockAppStore{ctrl: ctrl} - mock.recorder = &MockAppStoreMockRecorder{mock} +// NewMockApps creates a new mock instance. +func NewMockApps(ctrl *gomock.Controller) *MockApps { + mock := &MockApps{ctrl: ctrl} + mock.recorder = &MockAppsMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockAppStore) EXPECT() *MockAppStoreMockRecorder { +func (m *MockApps) EXPECT() *MockAppsMockRecorder { return m.recorder } // AsList mocks base method. -func (m *MockAppStore) AsList(arg0 store.FilterOpt) []apps.App { +func (m *MockApps) AsList(arg0 store.FilterOpt) []apps.App { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AsList", arg0) ret0, _ := ret[0].([]apps.App) @@ -46,13 +45,13 @@ func (m *MockAppStore) AsList(arg0 store.FilterOpt) []apps.App { } // AsList indicates an expected call of AsList. -func (mr *MockAppStoreMockRecorder) AsList(arg0 interface{}) *gomock.Call { +func (mr *MockAppsMockRecorder) AsList(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AsList", reflect.TypeOf((*MockAppStore)(nil).AsList), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AsList", reflect.TypeOf((*MockApps)(nil).AsList), arg0) } // AsMap mocks base method. -func (m *MockAppStore) AsMap(arg0 store.FilterOpt) map[apps.AppID]apps.App { +func (m *MockApps) AsMap(arg0 store.FilterOpt) map[apps.AppID]apps.App { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "AsMap", arg0) ret0, _ := ret[0].(map[apps.AppID]apps.App) @@ -60,27 +59,13 @@ func (m *MockAppStore) AsMap(arg0 store.FilterOpt) map[apps.AppID]apps.App { } // AsMap indicates an expected call of AsMap. -func (mr *MockAppStoreMockRecorder) AsMap(arg0 interface{}) *gomock.Call { +func (mr *MockAppsMockRecorder) AsMap(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AsMap", reflect.TypeOf((*MockAppStore)(nil).AsMap), arg0) -} - -// Configure mocks base method. -func (m *MockAppStore) Configure(arg0 utils.Logger) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Configure", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// Configure indicates an expected call of Configure. -func (mr *MockAppStoreMockRecorder) Configure(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Configure", reflect.TypeOf((*MockAppStore)(nil).Configure), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AsMap", reflect.TypeOf((*MockApps)(nil).AsMap), arg0) } // Delete mocks base method. -func (m *MockAppStore) Delete(arg0 *incoming.Request, arg1 apps.AppID) error { +func (m *MockApps) Delete(arg0 *incoming.Request, arg1 apps.AppID) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1) ret0, _ := ret[0].(error) @@ -88,13 +73,13 @@ func (m *MockAppStore) Delete(arg0 *incoming.Request, arg1 apps.AppID) error { } // Delete indicates an expected call of Delete. -func (mr *MockAppStoreMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockAppsMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAppStore)(nil).Delete), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockApps)(nil).Delete), arg0, arg1) } // Get mocks base method. -func (m *MockAppStore) Get(arg0 apps.AppID) (*apps.App, error) { +func (m *MockApps) Get(arg0 apps.AppID) (*apps.App, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0) ret0, _ := ret[0].(*apps.App) @@ -103,13 +88,13 @@ func (m *MockAppStore) Get(arg0 apps.AppID) (*apps.App, error) { } // Get indicates an expected call of Get. -func (mr *MockAppStoreMockRecorder) Get(arg0 interface{}) *gomock.Call { +func (mr *MockAppsMockRecorder) Get(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockAppStore)(nil).Get), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockApps)(nil).Get), arg0) } // InitBuiltin mocks base method. -func (m *MockAppStore) InitBuiltin(arg0 ...apps.App) { +func (m *MockApps) InitBuiltin(arg0 ...apps.App) { m.ctrl.T.Helper() varargs := []interface{}{} for _, a := range arg0 { @@ -119,13 +104,13 @@ func (m *MockAppStore) InitBuiltin(arg0 ...apps.App) { } // InitBuiltin indicates an expected call of InitBuiltin. -func (mr *MockAppStoreMockRecorder) InitBuiltin(arg0 ...interface{}) *gomock.Call { +func (mr *MockAppsMockRecorder) InitBuiltin(arg0 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitBuiltin", reflect.TypeOf((*MockAppStore)(nil).InitBuiltin), arg0...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitBuiltin", reflect.TypeOf((*MockApps)(nil).InitBuiltin), arg0...) } // Save mocks base method. -func (m *MockAppStore) Save(arg0 *incoming.Request, arg1 apps.App) error { +func (m *MockApps) Save(arg0 *incoming.Request, arg1 apps.App) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Save", arg0, arg1) ret0, _ := ret[0].(error) @@ -133,7 +118,7 @@ func (m *MockAppStore) Save(arg0 *incoming.Request, arg1 apps.App) error { } // Save indicates an expected call of Save. -func (mr *MockAppStoreMockRecorder) Save(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockAppsMockRecorder) Save(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockAppStore)(nil).Save), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockApps)(nil).Save), arg0, arg1) } diff --git a/server/mocks/mock_store/mock_session.go b/server/mocks/mock_store/mock_session_store.go similarity index 51% rename from server/mocks/mock_store/mock_session.go rename to server/mocks/mock_store/mock_session_store.go index 4a455200a..854f235e7 100644 --- a/server/mocks/mock_store/mock_session.go +++ b/server/mocks/mock_store/mock_session_store.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/mattermost/mattermost-plugin-apps/server/store (interfaces: SessionStore) +// Source: github.com/mattermost/mattermost-plugin-apps/server/store (interfaces: Sessions) // Package mock_store is a generated GoMock package. package mock_store @@ -13,45 +13,45 @@ import ( model "github.com/mattermost/mattermost-server/v6/model" ) -// MockSessionStore is a mock of SessionStore interface. -type MockSessionStore struct { +// MockSessions is a mock of Sessions interface. +type MockSessions struct { ctrl *gomock.Controller - recorder *MockSessionStoreMockRecorder + recorder *MockSessionsMockRecorder } -// MockSessionStoreMockRecorder is the mock recorder for MockSessionStore. -type MockSessionStoreMockRecorder struct { - mock *MockSessionStore +// MockSessionsMockRecorder is the mock recorder for MockSessions. +type MockSessionsMockRecorder struct { + mock *MockSessions } -// NewMockSessionStore creates a new mock instance. -func NewMockSessionStore(ctrl *gomock.Controller) *MockSessionStore { - mock := &MockSessionStore{ctrl: ctrl} - mock.recorder = &MockSessionStoreMockRecorder{mock} +// NewMockSessions creates a new mock instance. +func NewMockSessions(ctrl *gomock.Controller) *MockSessions { + mock := &MockSessions{ctrl: ctrl} + mock.recorder = &MockSessionsMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockSessionStore) EXPECT() *MockSessionStoreMockRecorder { +func (m *MockSessions) EXPECT() *MockSessionsMockRecorder { return m.recorder } // Delete mocks base method. -func (m *MockSessionStore) Delete(arg0 apps.AppID, arg1 string) error { +func (m *MockSessions) Delete(arg0 *incoming.Request, arg1 apps.AppID, arg2 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", arg0, arg1) + ret := m.ctrl.Call(m, "Delete", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } // Delete indicates an expected call of Delete. -func (mr *MockSessionStoreMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockSessionsMockRecorder) Delete(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockSessionStore)(nil).Delete), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockSessions)(nil).Delete), arg0, arg1, arg2) } // DeleteAllForApp mocks base method. -func (m *MockSessionStore) DeleteAllForApp(arg0 *incoming.Request, arg1 apps.AppID) error { +func (m *MockSessions) DeleteAllForApp(arg0 *incoming.Request, arg1 apps.AppID) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteAllForApp", arg0, arg1) ret0, _ := ret[0].(error) @@ -59,13 +59,13 @@ func (m *MockSessionStore) DeleteAllForApp(arg0 *incoming.Request, arg1 apps.App } // DeleteAllForApp indicates an expected call of DeleteAllForApp. -func (mr *MockSessionStoreMockRecorder) DeleteAllForApp(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockSessionsMockRecorder) DeleteAllForApp(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllForApp", reflect.TypeOf((*MockSessionStore)(nil).DeleteAllForApp), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllForApp", reflect.TypeOf((*MockSessions)(nil).DeleteAllForApp), arg0, arg1) } // DeleteAllForUser mocks base method. -func (m *MockSessionStore) DeleteAllForUser(arg0 *incoming.Request, arg1 string) error { +func (m *MockSessions) DeleteAllForUser(arg0 *incoming.Request, arg1 string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteAllForUser", arg0, arg1) ret0, _ := ret[0].(error) @@ -73,43 +73,43 @@ func (m *MockSessionStore) DeleteAllForUser(arg0 *incoming.Request, arg1 string) } // DeleteAllForUser indicates an expected call of DeleteAllForUser. -func (mr *MockSessionStoreMockRecorder) DeleteAllForUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockSessionsMockRecorder) DeleteAllForUser(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllForUser", reflect.TypeOf((*MockSessionStore)(nil).DeleteAllForUser), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllForUser", reflect.TypeOf((*MockSessions)(nil).DeleteAllForUser), arg0, arg1) } // Get mocks base method. -func (m *MockSessionStore) Get(arg0 apps.AppID, arg1 string) (*model.Session, error) { +func (m *MockSessions) Get(arg0 *incoming.Request, arg1 apps.AppID, arg2 string) (*model.Session, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", arg0, arg1) + ret := m.ctrl.Call(m, "Get", arg0, arg1, arg2) ret0, _ := ret[0].(*model.Session) ret1, _ := ret[1].(error) return ret0, ret1 } // Get indicates an expected call of Get. -func (mr *MockSessionStoreMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockSessionsMockRecorder) Get(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSessionStore)(nil).Get), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSessions)(nil).Get), arg0, arg1, arg2) } // ListForApp mocks base method. -func (m *MockSessionStore) ListForApp(arg0 apps.AppID) ([]*model.Session, error) { +func (m *MockSessions) ListForApp(arg0 *incoming.Request, arg1 apps.AppID) ([]*model.Session, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ListForApp", arg0) + ret := m.ctrl.Call(m, "ListForApp", arg0, arg1) ret0, _ := ret[0].([]*model.Session) ret1, _ := ret[1].(error) return ret0, ret1 } // ListForApp indicates an expected call of ListForApp. -func (mr *MockSessionStoreMockRecorder) ListForApp(arg0 interface{}) *gomock.Call { +func (mr *MockSessionsMockRecorder) ListForApp(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListForApp", reflect.TypeOf((*MockSessionStore)(nil).ListForApp), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListForApp", reflect.TypeOf((*MockSessions)(nil).ListForApp), arg0, arg1) } // ListForUser mocks base method. -func (m *MockSessionStore) ListForUser(arg0 *incoming.Request, arg1 string) ([]*model.Session, error) { +func (m *MockSessions) ListForUser(arg0 *incoming.Request, arg1 string) ([]*model.Session, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListForUser", arg0, arg1) ret0, _ := ret[0].([]*model.Session) @@ -118,21 +118,21 @@ func (m *MockSessionStore) ListForUser(arg0 *incoming.Request, arg1 string) ([]* } // ListForUser indicates an expected call of ListForUser. -func (mr *MockSessionStoreMockRecorder) ListForUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockSessionsMockRecorder) ListForUser(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListForUser", reflect.TypeOf((*MockSessionStore)(nil).ListForUser), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListForUser", reflect.TypeOf((*MockSessions)(nil).ListForUser), arg0, arg1) } // Save mocks base method. -func (m *MockSessionStore) Save(arg0 apps.AppID, arg1 string, arg2 *model.Session) error { +func (m *MockSessions) Save(arg0 *incoming.Request, arg1 apps.AppID, arg2 string, arg3 *model.Session) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Save", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "Save", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(error) return ret0 } // Save indicates an expected call of Save. -func (mr *MockSessionStoreMockRecorder) Save(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockSessionsMockRecorder) Save(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockSessionStore)(nil).Save), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockSessions)(nil).Save), arg0, arg1, arg2, arg3) } diff --git a/server/plugin.go b/server/plugin.go index 0b99f1528..2f2108e9e 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -96,13 +96,18 @@ func (p *Plugin) OnActivate() (err error) { // Initialize outgoing HTTP. p.httpOut = httpout.NewService(p.conf) - // Initialize persistent storage. Also initialize the app API and the - // session services, both need the persisitent store. - p.store, err = store.MakeService(p.conf, p.httpOut) + // Initialize persistent stores. + p.store, err = store.MakeService(p.conf, store.SingleWriterCachedStoreKind) if err != nil { - return errors.Wrap(err, "failed to initialize persistent store") + return errors.Wrap(err, "failed to initialize the manifest store") + } + + if conf.MattermostCloudMode { + err = p.store.Manifest.InitCloudCatalog(p.conf, p.httpOut) + if err != nil { + return errors.Wrap(err, "failed to initialize the manifest store") + } } - p.store.App.InitBuiltin(builtin.App(conf)) // Initialize services (API implementations) - session, app services, proxy. p.appservices = appservices.NewService(p.store) @@ -110,7 +115,7 @@ func (p *Plugin) OnActivate() (err error) { log.Debugf("initialized API and persistent store") // Initialize the app proxy. - mutex, err := cluster.NewMutex(p.API, store.KVClusterMutexKey) + mutex, err := cluster.NewMutex(p.API, store.ClusterMutexKey) if err != nil { return errors.Wrapf(err, "failed creating cluster mutex") } @@ -121,9 +126,9 @@ func (p *Plugin) OnActivate() (err error) { } log.Debugf("initialized the app proxy") - p.proxy.AddBuiltinUpstream( - builtin.AppID, - builtin.NewBuiltinApp(api, p.proxy, p.appservices, p.httpOut, p.sessionService)) + // Initialize the built-in "/apps" app. + p.store.App.InitBuiltin(builtin.App(conf)) + p.proxy.AddBuiltinUpstream(builtin.AppID, builtin.NewBuiltinApp(api, p.proxy, p.appservices, p.httpOut, p.sessionService)) log.Debugf("initialized the built-in app: use /apps command") p.httpIn = httpin.NewService(p.proxy, p.appservices, p.conf) @@ -189,6 +194,16 @@ func (p *Plugin) OnConfigurationChange() error { return nil } +func (p *Plugin) OnClusterLeaderChanged(isLeader bool) error { //nolint:unparam + p.conf.OnClusterLeaderChanged(isLeader) + return nil +} + +func (p *Plugin) OnPluginClusterEvent(c *plugin.Context, ev model.PluginClusterEvent) { + r := p.proxy.NewIncomingRequest("OnPluginClusterEvent", c.RequestId) + p.store.OnPluginClusterEvent(r, ev) +} + func (p *Plugin) ServeHTTP(c *plugin.Context, w gohttp.ResponseWriter, req *gohttp.Request) { // each router.ServeHTTP will create their own incoming.Request using the // HTTP headers, otherwise it's difficult to pass r down. diff --git a/server/proxy/bindings_test.go b/server/proxy/bindings_test.go index bc58da5b4..293d11549 100644 --- a/server/proxy/bindings_test.go +++ b/server/proxy/bindings_test.go @@ -20,7 +20,6 @@ import ( "github.com/mattermost/mattermost-plugin-apps/apps/path" "github.com/mattermost/mattermost-plugin-apps/server/config" "github.com/mattermost/mattermost-plugin-apps/server/incoming" - "github.com/mattermost/mattermost-plugin-apps/server/mocks/mock_store" "github.com/mattermost/mattermost-plugin-apps/server/mocks/mock_upstream" "github.com/mattermost/mattermost-plugin-apps/server/store" "github.com/mattermost/mattermost-plugin-apps/upstream" @@ -583,10 +582,8 @@ func TestRefreshBindingsEventAfterCall(t *testing.T) { }, }).WithMattermostAPI(pluginapi.NewClient(testAPI, testDriver)) - s, err := store.MakeService(conf, nil) + store, err := store.MakeService(conf, store.TestCachedStoreKind) require.NoError(t, err) - appStore := mock_store.NewMockAppStore(ctrl) - s.App = appStore upstreams := map[apps.AppID]upstream.Upstream{} for i := range tc.applications { @@ -600,11 +597,11 @@ func TestRefreshBindingsEventAfterCall(t *testing.T) { up.EXPECT().Roundtrip(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(reader, nil) upstreams[app.Manifest.AppID] = up - appStore.EXPECT().Get(app.Manifest.AppID).Return(&app, nil) + _ = store.App.Save(nil, app) } proxy := &Proxy{ - store: s, + store: store, builtinUpstreams: upstreams, conf: conf, } diff --git a/server/proxy/invoke_oauth2.go b/server/proxy/invoke_oauth2.go index 42bf3a4ae..f105d353e 100644 --- a/server/proxy/invoke_oauth2.go +++ b/server/proxy/invoke_oauth2.go @@ -19,7 +19,7 @@ func (p *Proxy) InvokeGetRemoteOAuth2ConnectURL(r *incoming.Request) (string, er return "", errors.Errorf("%s is not authorized to use OAuth2", app.AppID) } - state, err := p.store.OAuth2.CreateState(r.ActingUserID()) + state, err := p.store.OAuth2.CreateState(r) if err != nil { return "", err } @@ -53,7 +53,7 @@ func (p *Proxy) InvokeCompleteRemoteOAuth2(r *incoming.Request, urlValues map[st if urlState == "" { return utils.NewUnauthorizedError("no state arg in the URL") } - err = p.store.OAuth2.ValidateStateOnce(urlState, r.ActingUserID()) + err = p.store.OAuth2.ValidateStateOnce(r, urlState) if err != nil { return err } diff --git a/server/proxy/notify.go b/server/proxy/notify.go index dd8a77140..b4646cc2d 100644 --- a/server/proxy/notify.go +++ b/server/proxy/notify.go @@ -215,7 +215,7 @@ func (p *Proxy) notifyAll(r *incoming.Request, event apps.Event, uac apps.UserAg } r.Log = r.Log.With(event) - subs, err := p.store.Subscription.Get(event) + subs, err := p.store.Subscription.Get(r, event) if err != nil { r.Log.WithError(err).Errorf("notify: failed to load subscriptions") return diff --git a/server/proxy/synchronize.go b/server/proxy/synchronize.go index 6385f1275..bf54bad84 100644 --- a/server/proxy/synchronize.go +++ b/server/proxy/synchronize.go @@ -72,7 +72,7 @@ func (p *Proxy) SynchronizeInstalledApps() error { func (p *Proxy) callOnce(r *incoming.Request, f func() error) error { // Delete previous job - if err := r.API.Mattermost.KV.Delete(store.KVCallOnceKey); err != nil { + if err := r.API.Mattermost.KV.Delete(store.CallOnceKey); err != nil { return errors.Wrap(err, "can't delete key") } // Ensure all instances run this @@ -81,7 +81,7 @@ func (p *Proxy) callOnce(r *incoming.Request, f func() error) error { p.callOnceMutex.Lock() defer p.callOnceMutex.Unlock() value := 0 - if err := r.API.Mattermost.KV.Get(store.KVCallOnceKey, &value); err != nil { + if err := r.API.Mattermost.KV.Get(store.CallOnceKey, &value); err != nil { return err } if value != 0 { @@ -94,12 +94,12 @@ func (p *Proxy) callOnce(r *incoming.Request, f func() error) error { return errors.Wrap(err, "can't run the job") } value = 1 - ok, err := r.API.Mattermost.KV.Set(store.KVCallOnceKey, value) + ok, err := r.API.Mattermost.KV.Set(store.CallOnceKey, value) if err != nil { - return errors.Wrapf(err, "can't set key %s to %d", store.KVCallOnceKey, value) + return errors.Wrapf(err, "can't set key %s to %d", store.CallOnceKey, value) } if !ok { - return errors.Errorf("can't set key %s to %d", store.KVCallOnceKey, value) + return errors.Errorf("can't set key %s to %d", store.CallOnceKey, value) } return nil } diff --git a/server/proxy/uninstall.go b/server/proxy/uninstall.go index f2c4a1bef..c373bf067 100644 --- a/server/proxy/uninstall.go +++ b/server/proxy/uninstall.go @@ -6,13 +6,15 @@ package proxy import ( "fmt" + "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "github.com/mattermost/mattermost-plugin-apps/apps" "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" ) -func (p *Proxy) UninstallApp(r *incoming.Request, cc apps.Context, appID apps.AppID, force bool) (text string, err error) { +func (p *Proxy) UninstallApp(r *incoming.Request, cc apps.Context, appID apps.AppID, force bool) (_ string, err error) { if err = r.Check( r.RequireActingUser, r.RequireSysadminOrPlugin, @@ -22,72 +24,125 @@ func (p *Proxy) UninstallApp(r *incoming.Request, cc apps.Context, appID apps.Ap app, err := p.store.App.Get(appID) if err != nil { - return "", errors.Wrapf(err, "failed to get app, appID: %s", appID) + return "", errors.Wrapf(err, "failed to get app for appID: %s", appID) } - message := fmt.Sprintf("Uninstalled %s", app.DisplayName) + u := uninstaller{ + deleteApp: func() error { return p.store.App.Delete(r, appID) }, + deleteAppData: func() error { return p.appservices.DeleteAppData(r, appID, force) }, + deleteMattermostOAuth2App: func() error { return r.API.Mattermost.OAuth.Delete(app.MattermostOAuth2.Id) }, + disableApp: func() error { _, e := p.DisableApp(r, cc, appID); return e }, + disableBotAccount: func() error { _, e := r.API.Mattermost.Bot.UpdateActive(app.BotUserID, false); return e }, + revokeSessionsForApp: func() error { return p.store.Session.DeleteAllForApp(r, app.AppID) }, + uninstallCall: func() apps.CallResponse { return p.call(r, app, *app.OnUninstall, &cc) }, + log: r.Log, + } + + message, err := u.uninstall(app, force) + if err != nil { + return "", err + } + + r.Log.Infof("Uninstalled app %s.", appID) + + r.API.Telemetry.TrackUninstall(string(app.AppID), string(app.DeployType)) + + p.dispatchRefreshBindingsEvent(r) + + return message, nil +} + +type uninstaller struct { + deleteApp func() error + deleteAppData func() error + deleteMattermostOAuth2App func() error + disableApp func() error + disableBotAccount func() error + revokeSessionsForApp func() error + uninstallCall func() apps.CallResponse + log utils.Logger +} + +func (u uninstaller) uninstall(app *apps.App, force bool) (_ string, err error) { + var errs *multierror.Error + // Log errors on exit. + defer func() { + switch { + case err != nil: + u.log.WithError(err).Errorf("failed to uninstall app: %v", err) + case force && errs != nil: + u.log.Errorf("force-uninstalled app despite errors: %v", errs) + } + }() + + // Helper to wrap, and to log errors and continue if force is true. + forceIgnoreErrors := func(e error, text string) error { + if e == nil { + return nil + } + if text != "" { + e = errors.Wrap(e, string(app.AppID)+": "+text) + } + if !force { + return e + } + errs = multierror.Append(errs, e) + return nil + } + + // Give the app a chance to clean up. + var onUninstallResponse apps.CallResponse if app.OnUninstall != nil { - resp := p.call(r, app, *app.OnUninstall, &cc) - switch resp.Type { - case apps.CallResponseTypeError: - if !force { - return "", errors.Wrap(resp, "app canceled uninstall request") + onUninstallResponse = u.uninstallCall() + if onUninstallResponse.Type == apps.CallResponseTypeError { + if err = forceIgnoreErrors(onUninstallResponse, "app canceled uninstall"); err != nil { + return "", err } - message = fmt.Sprintf("Force-uninstalled %s, despite error: %s", app.DisplayName, resp.Text) - - case apps.CallResponseTypeOK: - message = fmt.Sprintf("Uninstalled %s, with message: %s", app.DisplayName, resp.Text) } } - // If the app's cleanup fails in the middle, disable the app and return the error. + // If the app's data cleanup fails in the middle, disable the app. defer func() { - if err == nil { - return - } - r.Log.WithError(err).Errorf("Failed to uninstall app %s: %v", appID, errors.Cause(err)) - if _, disableErr := p.DisableApp(r, cc, appID); disableErr != nil { - r.Log.WithError(disableErr).Errorf("Failed to disable app %s after a failed uninstall: %v", appID, errors.Cause(disableErr)) + if err != nil { + err = errors.Wrap(err, "disabled app after failing to clean up its data") + if disableErr := u.disableApp(); disableErr != nil { + err = multierror.Append(&multierror.Error{}, + errors.Wrap(err, "failed to clean up app data on uninstall"), + errors.Wrap(disableErr, "failed to disable app after failing to clean up its data")) + } } }() // Only clear the session store. Existing session are revoked when the OAuth app gets deleted. - if err = p.store.Session.DeleteAllForApp(r, app.AppID); err != nil { - return "", errors.Wrapf(err, "failed to revoke sessions for %s", app.AppID) + if err = forceIgnoreErrors(u.revokeSessionsForApp(), "failed to revoke sessions"); err != nil { + return "", err } - // Delete OAuth app. if app.MattermostOAuth2 != nil { - if err = r.API.Mattermost.OAuth.Delete(app.MattermostOAuth2.Id); err != nil { - return "", errors.Wrapf(err, "failed to delete Mattermost OAuth2 for %s, the app is left disabled", appID) + if err = forceIgnoreErrors(u.deleteMattermostOAuth2App(), "failed to delete Mattermost OAuth2 app record"); err != nil { + return "", err } } - // Disable the app's bot account. - if _, err = r.API.Mattermost.Bot.UpdateActive(app.BotUserID, false); err != nil { - return "", errors.Wrapf(err, "failed to disable bot account for %s, the app is left disabled", appID) + if err = forceIgnoreErrors(u.disableBotAccount(), "failed to disable Mattermost bot account"); err != nil { + return "", err } - // Remove all KV and user data. - if err = p.store.RemoveAllKVAndUserDataForApp(r, appID); err != nil { - return "", errors.Wrapf(err, "failed to clear app data for %s, the app is left disabled", appID) + if err = forceIgnoreErrors(u.deleteAppData(), "failed to clean app's persisted data"); err != nil { + return "", err } - // Remove all subscriptions. - if err = p.appservices.UnsubscribeApp(r, appID); err != nil { - return "", errors.Wrapf(err, "failed to clear subscriptions for %s, the app is left disabled", appID) + if err = u.deleteApp(); err != nil { + return "", errors.Wrapf(err, "failed to delete app") } - // Delete the main record of the app. - if err = p.store.App.Delete(r, app.AppID); err != nil { - return "", errors.Wrapf(err, "can't delete app %s, the app is left disabled", appID) + message := fmt.Sprintf("Uninstalled %s (%s)", app.AppID, app.DisplayName) + switch { + case force && errs != nil: + message = fmt.Sprintf("Force-uninstalled %s (%s), despite error(s): %v", app.AppID, app.DisplayName, errs) + case onUninstallResponse.Text != "": + message = fmt.Sprintf("Uninstalled %s (%s), with message: %s", app.AppID, app.DisplayName, onUninstallResponse.Text) } - r.Log.Infof("Uninstalled app %s.", appID) - - r.API.Telemetry.TrackUninstall(string(app.AppID), string(app.DeployType)) - - p.dispatchRefreshBindingsEvent(r) - return message, nil } diff --git a/server/proxy/uninstall_test.go b/server/proxy/uninstall_test.go new file mode 100644 index 000000000..6480b3acf --- /dev/null +++ b/server/proxy/uninstall_test.go @@ -0,0 +1,158 @@ +// Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +package proxy + +import ( + "fmt" + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/mattermost/mattermost-server/v6/model" + + "github.com/mattermost/mattermost-plugin-apps/apps" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +func TestUninstallApp(t *testing.T) { + for _, tc := range []struct { + name string + u uninstaller + expectedError string + expectedMessage string + expectedForceError string + expectedForceMessage string + }{ + { + name: "happy path", + u: uninstaller{}, + expectedMessage: "Uninstalled appID (test app)", + expectedForceMessage: "Uninstalled appID (test app)", + }, + { + name: "deleteApp error", + u: uninstaller{ + deleteApp: func() error { return errors.New("deleteApp error") }, + }, + expectedError: "disabled app after failing to clean up its data: failed to delete app: deleteApp error", + expectedForceError: "disabled app after failing to clean up its data: failed to delete app: deleteApp error", + }, + { + name: "deleteAppData error", + u: uninstaller{ + deleteAppData: func() error { return errors.New("deleteAppData error") }, + }, + expectedError: "disabled app after failing to clean up its data: appID: failed to clean app's persisted data: deleteAppData error", + expectedForceMessage: "Force-uninstalled appID (test app), despite error(s): 1 error occurred:\n\t* appID: failed to clean app's persisted data: deleteAppData error\n\n", + }, + { + name: "deleteMattermostOAuth2App", + u: uninstaller{ + deleteMattermostOAuth2App: func() error { return errors.New("deleteMattermostOAuth2App error") }, + }, + expectedError: "disabled app after failing to clean up its data: appID: failed to delete Mattermost OAuth2 app record: deleteMattermostOAuth2App error", + expectedForceMessage: "Force-uninstalled appID (test app), despite error(s): 1 error occurred:\n\t* appID: failed to delete Mattermost OAuth2 app record: deleteMattermostOAuth2App error\n\n", + }, + { + name: "disableApp", + u: uninstaller{ + // need to trigger disableApp, so return a cleanup error + revokeSessionsForApp: func() error { return errors.New("revokeSessionsForApp error") }, + disableApp: func() error { return errors.New("disableApp error") }, + }, + expectedError: "2 errors occurred:\n\t* failed to clean up app data on uninstall: disabled app after failing to clean up its data: appID: failed to revoke sessions: revokeSessionsForApp error\n\t* failed to disable app after failing to clean up its data: disableApp error\n\n", + expectedForceMessage: "Force-uninstalled appID (test app), despite error(s): 1 error occurred:\n\t* appID: failed to revoke sessions: revokeSessionsForApp error\n\n", + }, + { + name: "disableBotAccount", + u: uninstaller{ + disableBotAccount: func() error { return errors.New("disableBotAccount error") }, + }, + expectedError: "disabled app after failing to clean up its data: appID: failed to disable Mattermost bot account: disableBotAccount error", + expectedForceMessage: "Force-uninstalled appID (test app), despite error(s): 1 error occurred:\n\t* appID: failed to disable Mattermost bot account: disableBotAccount error\n\n", + }, + { + name: "revokeSessionsForApp", + u: uninstaller{ + revokeSessionsForApp: func() error { return errors.New("revokeSessionsForApp error") }, + }, + expectedError: "disabled app after failing to clean up its data: appID: failed to revoke sessions: revokeSessionsForApp error", + expectedForceMessage: "Force-uninstalled appID (test app), despite error(s): 1 error occurred:\n\t* appID: failed to revoke sessions: revokeSessionsForApp error\n\n", + }, + { + name: "uninstallCall", + u: uninstaller{ + uninstallCall: func() apps.CallResponse { + return apps.CallResponse{ + Type: apps.CallResponseTypeError, + Text: "uninstallCall error", + } + }, + }, + expectedError: "appID: app canceled uninstall: uninstallCall error", + expectedForceMessage: "Force-uninstalled appID (test app), despite error(s): 1 error occurred:\n\t* appID: app canceled uninstall: uninstallCall error\n\n", + }, + { + name: "multiple errors", + u: uninstaller{ + revokeSessionsForApp: func() error { return errors.New("revokeSessionsForApp error") }, + deleteAppData: func() error { return errors.New("deleteAppData error") }, + deleteMattermostOAuth2App: func() error { return errors.New("deleteMattermostOAuth2App error") }, + }, + expectedError: "disabled app after failing to clean up its data: appID: failed to revoke sessions: revokeSessionsForApp error", + expectedForceMessage: "Force-uninstalled appID (test app), despite error(s): 3 errors occurred:\n\t* appID: failed to revoke sessions: revokeSessionsForApp error\n\t* appID: failed to delete Mattermost OAuth2 app record: deleteMattermostOAuth2App error\n\t* appID: failed to clean app's persisted data: deleteAppData error\n\n", + }, + } { + for _, force := range []bool{false, true} { + t.Run(fmt.Sprintf("%s-%v", tc.name, force), func(t *testing.T) { + tc.u.log = utils.NilLogger{} + if tc.u.deleteApp == nil { + tc.u.deleteApp = func() error { return nil } + } + if tc.u.deleteAppData == nil { + tc.u.deleteAppData = func() error { return nil } + } + if tc.u.deleteMattermostOAuth2App == nil { + tc.u.deleteMattermostOAuth2App = func() error { return nil } + } + if tc.u.disableApp == nil { + tc.u.disableApp = func() error { return nil } + } + if tc.u.disableBotAccount == nil { + tc.u.disableBotAccount = func() error { return nil } + } + if tc.u.revokeSessionsForApp == nil { + tc.u.revokeSessionsForApp = func() error { return nil } + } + if tc.u.uninstallCall == nil { + tc.u.uninstallCall = func() apps.CallResponse { return apps.CallResponse{} } + } + + message, err := tc.u.uninstall(&apps.App{ + Manifest: apps.Manifest{ + AppID: "appID", + DisplayName: "test app", + OnUninstall: apps.NewCall("/on_uninstall"), + }, + MattermostOAuth2: &model.OAuthApp{}, + }, force) + expectedErr := tc.expectedError + expectedMessage := tc.expectedMessage + if force { + expectedErr = tc.expectedForceError + expectedMessage = tc.expectedForceMessage + } + + if expectedErr != "" { + require.Error(t, err) + require.Equal(t, expectedErr, err.Error()) + } else { + require.NoError(t, err) + } + require.Equal(t, expectedMessage, message) + }) + } + } +} diff --git a/server/proxy/update_app_listing.go b/server/proxy/update_app_listing.go index 76ae8a09b..359477eea 100644 --- a/server/proxy/update_app_listing.go +++ b/server/proxy/update_app_listing.go @@ -35,7 +35,7 @@ func (p *Proxy) UpdateAppListing(r *incoming.Request, req appclient.UpdateAppLis req.Manifest.Deploy = mergeDeployData(prevDeploy, req.Manifest.Deploy, req.AddDeploys, req.RemoveDeploys) } - err := p.store.Manifest.StoreLocal(r, req.Manifest) + err := p.store.Manifest.Save(r, req.Manifest) if err != nil { return nil, errors.Wrap(err, "failed to update listed manifest") } diff --git a/server/session/session.go b/server/session/session.go index 9b9d0069b..5a17141c8 100644 --- a/server/session/session.go +++ b/server/session/session.go @@ -39,7 +39,7 @@ func NewService(store *store.Service) Service { func (s *service) GetOrCreate(r *incoming.Request, userID string) (*model.Session, error) { appID := r.Destination() - session, err := s.store.Session.Get(appID, userID) + session, err := s.store.Session.Get(r, appID, userID) if err == nil && !session.IsExpired() { err = s.extendSessionExpiryIfNeeded(r, appID, userID, session) @@ -103,7 +103,7 @@ func (s *service) createSession(r *incoming.Request, appID apps.AppID, userID st return nil, errors.Wrap(err, "failed to create new app session") } - err = s.store.Session.Save(appID, userID, session) + err = s.store.Session.Save(r, appID, userID, session) if err != nil { return nil, errors.Wrap(err, "failed to save new session in store") } @@ -129,7 +129,7 @@ func (s *service) extendSessionExpiryIfNeeded(r *incoming.Request, appID apps.Ap // Update the store. session.ExpiresAt = newExpiryTime.UnixMilli() - err = s.store.Session.Save(appID, userID, session) + err = s.store.Session.Save(r, appID, userID, session) if err != nil { return errors.Wrap(err, "failed to save new session in store") } @@ -151,7 +151,7 @@ func (s service) revokeSessions(r *incoming.Request, sessions []*model.Session) } } - err := s.store.Session.Delete(sessionutils.GetAppID(session), session.UserId) + err := s.store.Session.Delete(r, sessionutils.GetAppID(session), session.UserId) if err != nil { r.Log.WithError(err).Warnw("failed to delete revoked session from store") } @@ -161,7 +161,7 @@ func (s service) revokeSessions(r *incoming.Request, sessions []*model.Session) } func (s service) RevokeSessionsForApp(r *incoming.Request, appID apps.AppID) error { - sessions, err := s.store.Session.ListForApp(appID) + sessions, err := s.store.Session.ListForApp(r, appID) if err != nil { return errors.Wrap(err, "failed to list app sessions for revocation") } diff --git a/server/session/session_test.go b/server/session/session_test.go index e275a9338..890d46b0e 100644 --- a/server/session/session_test.go +++ b/server/session/session_test.go @@ -22,24 +22,16 @@ import ( "github.com/mattermost/mattermost-plugin-apps/utils/sessionutils" ) -func setUpBasics(ctrl *gomock.Controller) (session.Service, - *incoming.Request, - *mock_store.MockSessionStore, - *mock_store.MockAppStore, - *plugintest.API) { - appStore := mock_store.NewMockAppStore(ctrl) - sessionStore := mock_store.NewMockSessionStore(ctrl) - mockStore := &store.Service{ - App: appStore, - Session: sessionStore, - } - +func setUpBasics(ctrl *gomock.Controller) (session.Service, *incoming.Request, *mock_store.MockSessions, *store.Service, *plugintest.API) { conf, api := config.NewTestService(nil) - r := incoming.NewRequest(conf, nil, "test", "reqid") - sessionService := session.NewService(mockStore) + sessionStore := mock_store.NewMockSessions(ctrl) + store, _ := store.MakeService(conf, store.TestCachedStoreKind) + store.Session = sessionStore + sessionService := session.NewService(store) - return sessionService, r, sessionStore, appStore, api + r := incoming.NewRequest(conf, sessionService, "test", "reqid") + return sessionService, r, sessionStore, store, api } func TestGetOrCreate(t *testing.T) { @@ -62,7 +54,7 @@ func TestGetOrCreate(t *testing.T) { } session.AddProp(model.SessionPropMattermostAppID, string(appID)) - sessionStore.EXPECT().Get(appID, userID).Times(1).Return(session, nil) + sessionStore.EXPECT().Get(gomock.Any(), appID, userID).Times(1).Return(session, nil) r = r.WithDestination(appID) rSession, err := sessionService.GetOrCreate(r, userID) @@ -89,9 +81,9 @@ func TestGetOrCreate(t *testing.T) { api.On("ExtendSessionExpiry", s.Id, mock.Anything).Once().Return(nil) s.AddProp(model.SessionPropMattermostAppID, string(appID)) - sessionStore.EXPECT().Get(appID, userID).Times(1).Return(&s, nil) + sessionStore.EXPECT().Get(gomock.Any(), appID, userID).Times(1).Return(&s, nil) - sessionStore.EXPECT().Save(appID, userID, gomock.Any()).Times(1).Return(nil) + sessionStore.EXPECT().Save(gomock.Any(), appID, userID, gomock.Any()).Times(1).Return(nil) r = r.WithDestination(appID) rSession, err := sessionService.GetOrCreate(r, userID) @@ -108,7 +100,7 @@ func TestGetOrCreate(t *testing.T) { t.Run("No session found", func(t *testing.T) { ctrl := gomock.NewController(t) - sessionService, r, sessionStore, appStore, api := setUpBasics(ctrl) + sessionService, r, sessionStore, store, api := setUpBasics(ctrl) appID := apps.AppID("foo") userID := model.NewId() @@ -147,11 +139,14 @@ func TestGetOrCreate(t *testing.T) { assert.Equal(t, newSession, rSession) }).Return(newSession, nil) - sessionStore.EXPECT().Get(appID, userID).Times(1).Return(nil, utils.ErrNotFound) - sessionStore.EXPECT().Save(appID, userID, gomock.Any()).Times(1).Return(nil) - appStore.EXPECT().Get(appID).Times(1).Return(&apps.App{ + sessionStore.EXPECT().Get(gomock.Any(), appID, userID).Times(1).Return(nil, utils.ErrNotFound) + sessionStore.EXPECT().Save(gomock.Any(), appID, userID, gomock.Any()).Times(1).Return(nil) + _ = store.App.Save(nil, apps.App{ + Manifest: apps.Manifest{ + AppID: appID, + }, MattermostOAuth2: oAuthApp, - }, nil) + }) r = r.WithDestination(appID) rSession, err := sessionService.GetOrCreate(r, userID) @@ -200,9 +195,9 @@ func TestRevokeSessionsForApp(t *testing.T) { session2.AddProp(model.SessionPropMattermostAppID, string(appID)) sessions := []*model.Session{session1, session2} - sessionStore.EXPECT().ListForApp(appID).Return(sessions, nil).Times(1) - sessionStore.EXPECT().Delete(appID, userID1).Return(nil).Times(1) - sessionStore.EXPECT().Delete(appID, userID2).Return(nil).Times(1) + sessionStore.EXPECT().ListForApp(gomock.Any(), appID).Return(sessions, nil).Times(1) + sessionStore.EXPECT().Delete(gomock.Any(), appID, userID1).Return(nil).Times(1) + sessionStore.EXPECT().Delete(gomock.Any(), appID, userID2).Return(nil).Times(1) api.On("RevokeSession", sessions[0].Id).Return(nil).Once() api.On("RevokeSession", sessions[1].Id).Return(nil).Once() diff --git a/server/store/appkv.go b/server/store/appkv.go index dd5b80831..21edc161b 100644 --- a/server/store/appkv.go +++ b/server/store/appkv.go @@ -5,24 +5,13 @@ import ( "github.com/mattermost/mattermost-plugin-apps/utils" ) -type AppKVStore interface { - Set(_ *incoming.Request, prefix, id string, data []byte) (bool, error) - Get(_ *incoming.Request, prefix, id string) ([]byte, error) - Delete(_ *incoming.Request, prefix, id string) error - List(_ *incoming.Request, namespace string, processf func(key string) error) error -} - -type appKVStore struct { - *Service -} - -var _ AppKVStore = (*appKVStore)(nil) +type KVStore struct{} -func (s *appKVStore) Set(r *incoming.Request, prefix, id string, data []byte) (bool, error) { +func (s *KVStore) Set(r *incoming.Request, prefix, id string, data []byte) (bool, error) { if r.SourceAppID() == "" || r.ActingUserID() == "" { return false, utils.NewInvalidError("source app ID or user ID missing in the request") } - key, err := Hashkey(KVAppPrefix, r.SourceAppID(), r.ActingUserID(), prefix, id) + key, err := Hashkey(KVPrefix, r.SourceAppID(), r.ActingUserID(), prefix, id) if err != nil { return false, err } @@ -37,8 +26,8 @@ func (s *appKVStore) Set(r *incoming.Request, prefix, id string, data []byte) (b return set, nil } -func (s *appKVStore) Get(r *incoming.Request, prefix, id string) ([]byte, error) { - key, err := Hashkey(KVAppPrefix, r.SourceAppID(), r.ActingUserID(), prefix, id) +func (s *KVStore) Get(r *incoming.Request, prefix, id string) ([]byte, error) { + key, err := Hashkey(KVPrefix, r.SourceAppID(), r.ActingUserID(), prefix, id) if err != nil { return nil, err } @@ -51,8 +40,8 @@ func (s *appKVStore) Get(r *incoming.Request, prefix, id string) ([]byte, error) return data, err } -func (s *appKVStore) Delete(r *incoming.Request, prefix, id string) error { - key, err := Hashkey(KVAppPrefix, r.SourceAppID(), r.ActingUserID(), prefix, id) +func (s *KVStore) Delete(r *incoming.Request, prefix, id string) error { + key, err := Hashkey(KVPrefix, r.SourceAppID(), r.ActingUserID(), prefix, id) if err != nil { return err } @@ -65,9 +54,9 @@ func (s *appKVStore) Delete(r *incoming.Request, prefix, id string) error { return nil } -func (s *appKVStore) List(r *incoming.Request, namespace string, processf func(key string) error) error { - return s.ListHashKeys(r, processf, - WithPrefix(KVAppPrefix), +func (s *KVStore) List(r *incoming.Request, namespace string, processf func(key string) error) error { + return ListHashKeys(r, processf, + WithPrefix(KVPrefix), WithAppID(r.SourceAppID()), WithUserID(r.ActingUserID()), WithNamespace(namespace)) diff --git a/server/store/apps.go b/server/store/apps.go index 20b8086fd..6fde41a54 100644 --- a/server/store/apps.go +++ b/server/store/apps.go @@ -4,16 +4,9 @@ package store import ( - "crypto/sha1" // nolint:gosec - "encoding/json" - "fmt" "sort" - "sync" - - "github.com/pkg/errors" "github.com/mattermost/mattermost-plugin-apps/apps" - "github.com/mattermost/mattermost-plugin-apps/server/config" "github.com/mattermost/mattermost-plugin-apps/server/incoming" "github.com/mattermost/mattermost-plugin-apps/utils" ) @@ -25,225 +18,89 @@ const ( AllApps = FilterOpt(true) ) -type AppStore interface { - config.Configurable - - InitBuiltin(...apps.App) - - Get(apps.AppID) (*apps.App, error) - AsList(FilterOpt) []apps.App - AsMap(FilterOpt) map[apps.AppID]apps.App - Save(*incoming.Request, apps.App) error - Delete(*incoming.Request, apps.AppID) error -} - // appStore combines installed and builtin Apps. The installed Apps are stored // in KV store, and the list of their keys is stored in the config, as a map of // AppID->sha1(App). -type appStore struct { - *Service - - // mutex guards installed, the pointer to the map of locally-installed apps. - mutex sync.RWMutex +type AppStore struct { + schemaVersion string + builtin map[apps.AppID]apps.App + CachedStore[apps.App] +} - installed map[apps.AppID]apps.App - builtinInstalled map[apps.AppID]apps.App +type Apps interface { + AsList(FilterOpt) []apps.App + AsMap(FilterOpt) map[apps.AppID]apps.App + Delete(*incoming.Request, apps.AppID) error + Get(apps.AppID) (*apps.App, error) + InitBuiltin(builtinApps ...apps.App) + Save(*incoming.Request, apps.App) error } -var _ AppStore = (*appStore)(nil) +var _ Apps = (*AppStore)(nil) -func (s *Service) makeAppStore() (*appStore, error) { - appStore := &appStore{Service: s} - err := appStore.Configure(s.conf.NewBaseLogger()) +func (s *Service) makeAppStore(version string, log utils.Logger) (*AppStore, error) { + store, err := MakeCachedStore[apps.App](AppStoreName, s.cluster, log) if err != nil { - return nil, errors.Wrap(err, "failed to initialize App store") + return nil, err } - return appStore, nil + return &AppStore{ + schemaVersion: version, + CachedStore: store, + }, nil } -func (s *appStore) InitBuiltin(builtinApps ...apps.App) { - s.mutex.Lock() - if s.builtinInstalled == nil { - s.builtinInstalled = map[apps.AppID]apps.App{} - } +func (s *AppStore) InitBuiltin(builtinApps ...apps.App) { + builtin := map[apps.AppID]apps.App{} for _, app := range builtinApps { app.DeployType = apps.DeployBuiltin - s.builtinInstalled[app.AppID] = app + builtin[app.AppID] = app } - s.mutex.Unlock() + s.builtin = builtin } -func (s *appStore) Configure(log utils.Logger) error { - newInstalled := map[apps.AppID]apps.App{} - for id, key := range s.conf.Get().InstalledApps { - log = log.With("app_id", id) - - var data []byte - err := s.conf.API().Mattermost.KV.Get(KVInstalledAppPrefix+key, &data) - if err != nil { - log.WithError(err).Errorw("failed to load app") - continue - } - - if len(data) == 0 { - err = utils.NewNotFoundError(KVInstalledAppPrefix + key) - log.WithError(err).Errorw("failed to load app") - continue - } - - app, err := apps.DecodeCompatibleApp(data) - if err != nil { - log.WithError(err).Errorw("failed to decode app") - continue - } - newInstalled[apps.AppID(id)] = *app - } - - s.mutex.Lock() - s.installed = newInstalled - s.mutex.Unlock() - return nil -} - -func (s *appStore) Get(appID apps.AppID) (*apps.App, error) { - s.mutex.RLock() - installed := s.installed - builtin := s.builtinInstalled - s.mutex.RUnlock() - - app, ok := builtin[appID] - if ok { +func (s *AppStore) Get(appID apps.AppID) (*apps.App, error) { + if app, ok := s.builtin[appID]; ok { return &app, nil } - app, ok = installed[appID] - if ok { - return &app, nil + if app := s.CachedStore.Get(string(appID)); app != nil { + return app, nil } return nil, utils.NewNotFoundError("app %s is not installed", appID) } -func (s *appStore) AsList(filter FilterOpt) []apps.App { - var out []apps.App - for _, app := range s.AsMap(filter) { - out = append(out, app) - } - sort.SliceStable(out, func(i, j int) bool { - return apps.AppID(out[i].DisplayName) < apps.AppID(out[j].DisplayName) - }) - return out -} - -func (s *appStore) AsMap(filter FilterOpt) map[apps.AppID]apps.App { - s.mutex.RLock() - installed := s.installed - builtin := s.builtinInstalled - s.mutex.RUnlock() - +func (s *AppStore) AsMap(filter FilterOpt) map[apps.AppID]apps.App { out := map[apps.AppID]apps.App{} - for appID, app := range installed { - if filter == AllApps || !app.Disabled { - out[appID] = app + for id := range s.Index() { + if app := s.CachedStore.Get(id); app != nil { + if filter == AllApps || !app.Disabled { + out[apps.AppID(id)] = *app + } } } - for appID, app := range builtin { + for appID, app := range s.builtin { if filter == AllApps || !app.Disabled { out[appID] = app } } - return out } -func (s *appStore) Save(r *incoming.Request, app apps.App) error { - conf := s.conf.Get() - prevSHA := conf.InstalledApps[string(app.AppID)] - - app.Manifest.SchemaVersion = conf.PluginManifest.Version - data, err := json.Marshal(app) - if err != nil { - return err - } - sha := fmt.Sprintf("%x", sha1.Sum(data)) // nolint:gosec - _, err = r.API.Mattermost.KV.Set(KVInstalledAppPrefix+sha, app) - if err != nil { - return err - } - - s.mutex.RLock() - installed := s.installed - s.mutex.RUnlock() - updatedInstalled := map[apps.AppID]apps.App{} - for k, v := range installed { - if k != app.AppID { - updatedInstalled[k] = v - } - } - updatedInstalled[app.AppID] = app - s.mutex.Lock() - s.installed = updatedInstalled - s.mutex.Unlock() - - sc := conf.StoredConfig - updated := map[string]string{} - for k, v := range conf.InstalledApps { - // delete prevSHA from the list by skipping - if v != prevSHA { - updated[k] = v - } - } - updated[string(app.AppID)] = sha - sc.InstalledApps = updated - err = s.conf.StoreConfig(sc, r.Log) - if err != nil { - return err - } - - if sha != prevSHA { - err = r.API.Mattermost.KV.Delete(KVInstalledAppPrefix + prevSHA) - if err != nil { - r.Log.WithError(err).Warnf("Failed to delete previous App KV value") - } +func (s *AppStore) AsList(filter FilterOpt) []apps.App { + var out []apps.App + for _, app := range s.AsMap(filter) { + out = append(out, app) } - - return nil + sort.SliceStable(out, func(i, j int) bool { + return apps.AppID(out[i].DisplayName) < apps.AppID(out[j].DisplayName) + }) + return out } -func (s *appStore) Delete(r *incoming.Request, appID apps.AppID) error { - s.mutex.RLock() - installed := s.installed - s.mutex.RUnlock() - _, ok := installed[appID] - if !ok { - return utils.NewNotFoundError(appID) - } - - conf := s.conf.Get() - sha, ok := conf.InstalledApps[string(appID)] - if !ok { - return utils.ErrNotFound - } - - err := r.API.Mattermost.KV.Delete(KVInstalledAppPrefix + sha) - if err != nil { - return err - } - - updatedInstalled := map[apps.AppID]apps.App{} - for k, v := range installed { - if k != appID { - updatedInstalled[k] = v - } - } - s.mutex.Lock() - s.installed = updatedInstalled - s.mutex.Unlock() +func (s *AppStore) Save(r *incoming.Request, app apps.App) error { + app.Manifest.SchemaVersion = s.schemaVersion + return s.CachedStore.Put(r, string(app.AppID), &app) +} - sc := conf.StoredConfig - updated := map[string]string{} - for k, v := range conf.InstalledApps { - updated[k] = v - } - delete(updated, string(appID)) - sc.InstalledApps = updated - return s.conf.StoreConfig(sc, r.Log) +func (s *AppStore) Delete(r *incoming.Request, appID apps.AppID) error { + return s.CachedStore.Put(r, string(appID), nil) } diff --git a/server/store/cached.go b/server/store/cached.go new file mode 100644 index 000000000..f8708ecc1 --- /dev/null +++ b/server/store/cached.go @@ -0,0 +1,124 @@ +// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +package store + +import ( + "crypto/sha256" + "fmt" + "sort" + + "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +type Cloneable[T any] interface { + Clone() *T +} + +// CachedStore is a cluster-aware write-through in-memory cache for entities such as [Apps] or [Subscriptions] +type CachedStore[T Cloneable[T]] interface { + Index() CachedIndex[T] + Get(key string) (value *T) + Put(r *incoming.Request, key string, value *T) error +} + +func MakeCachedStore[T Cloneable[T]](name string, cluster *CachedStoreCluster, log utils.Logger) (CachedStore[T], error) { + return makeCachedStore[T](cluster.defaultStoreKind, name, cluster, log) +} + +func makeCachedStore[T Cloneable[T]](kind CachedStoreClusterKind, name string, cluster *CachedStoreCluster, log utils.Logger) (CachedStore[T], error) { + switch kind { + case MutexCachedStoreKind: + return MakeMutexCachedStore[T](name, cluster, log) + case SingleWriterCachedStoreKind: + return MakeSingleWriterCachedStore[T](name, cluster, log) + case SimpleCachedStoreKind: + return MakeSimpleCachedStore[T](name, cluster.api, log) + case TestCachedStoreKind: + return TestingCachedStore[T]{}, nil + default: + return nil, fmt.Errorf("unknown CachedStore kind %s", kind) + } +} + +type CachedIndexEntry[T any] struct { + Key string `json:"k"` + ValueHash string `json:"h"` + data *T +} + +type StoredIndex[T any] struct { + Data []CachedIndexEntry[T] +} + +type CachedIndex[T any] map[string]*CachedIndexEntry[T] + +func (index *StoredIndex[T]) String() string { + keys := []string{} + for _, item := range index.Data { + keys = append(keys, item.Key) + } + return fmt.Sprintf("%v `%s` %v", len(index.Data), utils.FirstN(index.hash(), 10), keys) +} + +func (entry *CachedIndexEntry[T]) String() string { + return entry.Key + "/" + entry.ValueHash +} + +func (index CachedIndex[T]) Stored() *StoredIndex[T] { + stored := &StoredIndex[T]{} + for _, v := range index { + stored.Data = append(stored.Data, *v) + } + stored.sort() + return stored +} + +func (index StoredIndex[T]) sort() { + sort.Slice(index.Data, func(i, j int) bool { + return index.Data[i].Key < index.Data[j].Key + }) +} + +func (index StoredIndex[T]) hash() string { + var b []byte + for _, item := range index.Data { + b = append(b, item.Key...) + b = append(b, item.ValueHash...) + } + return fmt.Sprintf("%x", sha256.Sum256(b)) +} + +func (index *StoredIndex[T]) compareTo(other *StoredIndex[T]) (change, remove []CachedIndexEntry[T]) { + otherData := other.Data + if otherData == nil { + otherData = []CachedIndexEntry[T]{} + } + indexData := index.Data + if indexData == nil { + indexData = []CachedIndexEntry[T]{} + } + + i, o := 0, 0 + for { + switch { + case i >= len(indexData): + return append(change, otherData[o:]...), remove + case o >= len(otherData): + return change, append(remove, indexData[i:]...) + case indexData[i].Key < otherData[o].Key: + remove = append(remove, indexData[i]) + i++ + case indexData[i].Key > otherData[o].Key: + change = append(change, otherData[o]) + o++ + default: + if indexData[i].ValueHash != otherData[o].ValueHash { + change = append(change, otherData[o]) + } + i++ + o++ + } + } +} diff --git a/server/store/cached_cluster.go b/server/store/cached_cluster.go new file mode 100644 index 000000000..79d301f05 --- /dev/null +++ b/server/store/cached_cluster.go @@ -0,0 +1,109 @@ +// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +package store + +import ( + "encoding/json" + "sync" + + "github.com/mattermost/mattermost-server/v6/model" + + "github.com/mattermost/mattermost-plugin-apps/server/config" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +type CachedStoreClusterKind string + +const ( + MutexCachedStoreKind = CachedStoreClusterKind("mutex") + SimpleCachedStoreKind = CachedStoreClusterKind("simple") + SingleWriterCachedStoreKind = CachedStoreClusterKind("cluster_leader") + TestCachedStoreKind = CachedStoreClusterKind("test") +) + +type CachedStoreCluster struct { + api config.API + eventHandlers *sync.Map // event name -> pluginClusterEventHandler + defaultStoreKind CachedStoreClusterKind +} + +type eventHandler func(r *incoming.Request, ev model.PluginClusterEvent) error + +const ( + putEventID = "cached_store_data" + syncEventID = "cached_store_sync" +) + +// cachedStoreClusterEvent is a cluster event sent between nodes. It works for +// both the mutex-based and the single writer implementations. If Key is set, +// the message instructs to modify the key. If Data is nil, it is a delete +// operation. If IndexHash set, the receiver attempts to re-sync to it from the +// KV store. differentiate between put and delete (nil) events. +type cachedStoreClusterEvent[T any] struct { + Value *T `json:"value,omitempty"` + IndexHash string `json:"index_hash,omitempty"` + Key string `json:"key"` + StoreName string `json:"name"` +} + +func NewCachedStoreCluster(api config.API, kind CachedStoreClusterKind) *CachedStoreCluster { + if kind == "" { + kind = SingleWriterCachedStoreKind + } + return &CachedStoreCluster{ + api: api, + eventHandlers: &sync.Map{}, + defaultStoreKind: kind, + } +} + +func (s *Service) OnPluginClusterEvent(r *incoming.Request, ev model.PluginClusterEvent) { + f, err := s.cluster.getEventHandler(ev) + if err != nil { + r.Log.WithError(err).Errorw("failed to find a handler for plugin cluster event") + return + } + err = f(r, ev) + if err != nil { + r.Log.WithError(err).Errorw("failed to handle plugin cluster event") + return + } +} + +func (c *CachedStoreCluster) broadcastEvent(r *incoming.Request, id string, data any) { + bb, err := json.Marshal(data) + if err != nil { + r.Log.WithError(err).Errorw("failed to marshal plugin cluster event") + return + } + + r = r.Clone() + go func() { + err = c.api.Plugin.PublishPluginClusterEvent( + model.PluginClusterEvent{Id: id, Data: bb}, + model.PluginClusterEventSendOptions{SendType: model.PluginClusterEventSendTypeReliable}, + ) + if err != nil { + r.Log.WithError(err).Errorw("failed to marshal plugin cluster event") + return + } + }() +} + +func (c *CachedStoreCluster) getEventHandler(ev model.PluginClusterEvent) (eventHandler, error) { + v, ok := c.eventHandlers.Load(ev.Id) + if !ok { + return nil, utils.NewInvalidError("OnPluginClusterEvent: no handler for %s", ev.Id) + } + f, ok := v.(eventHandler) + if !ok { + return nil, utils.NewInvalidError("OnPluginClusterEvent: handler for %s is wrong type %T, expected %T", ev.Id, v, f) + } + return f, nil +} + +func (c *CachedStoreCluster) setEventHandler(eventID string, h eventHandler) { + c.eventHandlers.Store(eventID, h) +} diff --git a/server/store/cached_mutex.go b/server/store/cached_mutex.go new file mode 100644 index 000000000..eb189e97e --- /dev/null +++ b/server/store/cached_mutex.go @@ -0,0 +1,126 @@ +// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +package store + +import ( + "encoding/json" + "fmt" + + "github.com/mattermost/mattermost-plugin-api/cluster" + "github.com/mattermost/mattermost-server/v6/model" + "github.com/pkg/errors" + + "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +// MutexCachedStore is a CachedStore that uses a cluster.Mutex to ensure only +// one of the nodes is writing to the KV store at a time. Other nodes get +// notifies with [CachedStoreClusterEvent] messages and update their in-memory +// caches accordingly. +type MutexCachedStore[T Cloneable[T]] struct { + *SimpleCachedStore[T] + cluster *CachedStoreCluster + kvMutex *cluster.Mutex +} + +func MakeMutexCachedStore[T Cloneable[T]](name string, c *CachedStoreCluster, log utils.Logger) (CachedStore[T], error) { + return makeMutexCachedStore[T](name, c, log) +} + +func makeMutexCachedStore[T Cloneable[T]](name string, c *CachedStoreCluster, log utils.Logger) (*MutexCachedStore[T], error) { + base, err := MakeSimpleCachedStore[T](name, c.api, log) + if err != nil { + return nil, err + } + s := &MutexCachedStore[T]{ + SimpleCachedStore: base, + cluster: c, + } + + mutex, err := cluster.NewMutex(s.api.Plugin, s.mutexKey()) + if err != nil { + return nil, errors.Wrapf(err, "failed to make a new cached store %s", s.name) + } + s.kvMutex = mutex + + c.setEventHandler(s.eventID(), s.onEvent) + + return s, nil +} + +func (s *MutexCachedStore[T]) Put(r *incoming.Request, key string, value *T) error { + // Ensure exclusive access to the KV store. + s.kvMutex.Lock() + + // Need to ensure the local index is up to date before we can update it. + if err := s.syncFromKV(); err != nil { + s.kvMutex.Unlock() + return errors.Wrapf(err, "failed to sync from KV store before updating key %s", key) + } + + updatedIndex, changed, err := s.SimpleCachedStore.update(r, true, key, value) + s.kvMutex.Unlock() + if err != nil { + return err + } + + r.Log.Debugf("<>/<> 1 %v", changed) + + if changed { + event := s.newPluginClusterEvent(key, value, updatedIndex.hash()) + s.cluster.broadcastEvent(r, s.eventID(), event) + } + return nil +} + +func (s *MutexCachedStore[T]) eventID() string { + return putEventID + "/" + s.name +} + +func (s *MutexCachedStore[T]) onEvent(r *incoming.Request, ev model.PluginClusterEvent) error { + event := cachedStoreClusterEvent[T]{} + err := json.Unmarshal(ev.Data, &event) + if err != nil { + return errors.Wrap(err, "failed to unmarshal cached store cluster event") + } + + var newEntry *CachedIndexEntry[T] + if event.Value != nil { + newEntry = &CachedIndexEntry[T]{ + Key: event.Key, + ValueHash: valueHash(event.Value), + data: event.Value, + } + } + s.SimpleCachedStore.updateCachedValue(event.Key, newEntry) + + h := s.Index().Stored().hash() + if h != event.IndexHash { + r.Log.Debugf("cluster event %s: %s: updated index hash `%s` mismatched expected `%s`, syncing from KV", s.name, ev.Id, h, event.IndexHash) + index, _, _, err := s.syncFromKVDetailed() + if err != nil { + return err + } + if h = index.hash(); h != event.IndexHash { + r.Log.Debugf("cluster event %s: %s: synced from KV, still hash mismatch: got `%s`, expected `%s`", s.name, ev.Id, h, event.IndexHash) + } + } else { + r.Log.Debugf("cluster event %s: %s: key has %s been updated", s.name, ev.Id, event.Key) + } + return nil +} + +func (s *MutexCachedStore[T]) newPluginClusterEvent(key string, data *T, indexHash string) cachedStoreClusterEvent[T] { + return cachedStoreClusterEvent[T]{ + StoreName: s.name, + Key: key, + Value: data, + IndexHash: indexHash, + } +} + +func (s *MutexCachedStore[T]) mutexKey() string { + return fmt.Sprintf("%s.%s-mutex", CachedPrefix, s.name) +} diff --git a/server/store/cached_mutex_test.go b/server/store/cached_mutex_test.go new file mode 100644 index 000000000..0f7de5ea7 --- /dev/null +++ b/server/store/cached_mutex_test.go @@ -0,0 +1,170 @@ +package store + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/mattermost/mattermost-server/v6/model" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/mattermost/mattermost-plugin-apps/server/config" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +type CachedStoreTestType struct { + ID string + Body string +} + +func (t CachedStoreTestType) Clone() *CachedStoreTestType { + return &t +} + +func TestMutexCachedStore(t *testing.T) { + // stateRE := `[A-Za-z0-9-_]+\.[A-Za-z0-9]` + // userID := `userid-test` + conf, api := config.NewTestService(nil) + + api.On("KVGet", ".cached.test-index").Once(). + Return([]byte(nil), (*model.AppError)(nil)) + + cluster := NewCachedStoreCluster(conf.API(), TestCachedStoreKind) + + s, err := makeMutexCachedStore[CachedStoreTestType]("test", cluster, conf.NewBaseLogger()) + require.NoError(t, err) + + r := incoming.NewRequest(conf, nil, "test", "reqid") + put := func(id string, data CachedStoreTestType, indexBefore, indexAfter string) { + api.On("KVSetWithOptions", "mutex_.cached.test-mutex", []byte{0x1}, mock.Anything).Once(). + Return(true, nil) + api.On("KVGet", ".cached.test-index").Once(). + Return([]byte(indexBefore), (*model.AppError)(nil)) + api.On("KVSetWithOptions", fmt.Sprintf(".cached.test-item-%s", id), []byte(utils.ToJSON(data)), mock.Anything).Once(). + Return(true, nil) + api.On("KVSetWithOptions", ".cached.test-index", []byte(indexAfter), mock.Anything).Once(). + Return(true, nil) + api.On("KVSetWithOptions", "mutex_.cached.test-mutex", []byte(nil), mock.Anything).Once(). + Return(true, nil) + + eventCalled := make(chan bool) + api.On( + "PublishPluginClusterEvent", + mock.Anything, + model.PluginClusterEventSendOptions{ + SendType: "reliable", + }, + ). + Once(). + Run( + func(args mock.Arguments) { + e, ok := args[0].(model.PluginClusterEvent) + require.True(t, ok) + require.Equal(t, "cached_store_data/test", e.Id) + require.NotEmpty(t, e.Data) + + var event cachedStoreClusterEvent[CachedStoreTestType] + err = json.Unmarshal(e.Data, &event) + require.NoError(t, err) + + require.Equal(t, "test", event.StoreName) + require.Equal(t, id, event.Key) + require.NotNil(t, event.Value) + require.Equal(t, data, *event.Value) + + opts, ok := args[1].(model.PluginClusterEventSendOptions) + require.True(t, ok) + require.Equal(t, "reliable", opts.SendType) + + eventCalled <- true + }). + Return(nil) + + require.NotNil(t, s.kvMutex) + err = s.Put(r, id, &data) + require.NoError(t, err) + + <-eventCalled + api.AssertExpectations(t) + } + + delete := func(id string, indexBefore, indexAfter string) { + api.On("KVSetWithOptions", "mutex_.cached.test-mutex", []byte{0x1}, mock.Anything).Once(). + Return(true, nil) + api.On("KVGet", ".cached.test-index").Once(). + Return([]byte(indexBefore), (*model.AppError)(nil)) + api.On("KVSetWithOptions", fmt.Sprintf(".cached.test-item-%s", id), []byte(nil), mock.Anything).Once(). + Return(true, nil) + api.On("KVSetWithOptions", ".cached.test-index", []byte(indexAfter), mock.Anything).Once(). + Return(true, nil) + + eventCalled := make(chan bool) + api.On( + "PublishPluginClusterEvent", + mock.Anything, + model.PluginClusterEventSendOptions{ + SendType: "reliable", + }, + ). + Once(). + Run( + func(args mock.Arguments) { + e, ok := args[0].(model.PluginClusterEvent) + require.True(t, ok) + require.Equal(t, "cached_store_data/test", e.Id) + require.NotEmpty(t, e.Data) + + var event cachedStoreClusterEvent[CachedStoreTestType] + err = json.Unmarshal(e.Data, &event) + require.NoError(t, err) + + require.Equal(t, "test", event.StoreName) + require.Equal(t, id, event.Key) + require.Nil(t, event.Value) + + opts, ok := args[1].(model.PluginClusterEventSendOptions) + require.True(t, ok) + require.Equal(t, "reliable", opts.SendType) + + eventCalled <- true + }). + Return(nil) + + api.On("KVSetWithOptions", "mutex_.cached.test-mutex", []byte(nil), mock.Anything).Once(). + Return(true, nil) + + err = s.Put(r, id, nil) + require.NoError(t, err) + + <-eventCalled + api.AssertExpectations(t) + } + + t.Run("happy put and delete", func(t *testing.T) { + put("1", + CachedStoreTestType{ID: "1", Body: "test1"}, + ``, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"}]}`, + ) + put("2", + CachedStoreTestType{ID: "2", Body: "test2"}, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"}]}`, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"},{"k":"2","h":"76e8644d57eabcb1b39ae54908855de7bb6b53426f1519d88e772e16a18112ce"}]}`) + + put("3", + CachedStoreTestType{ID: "3", Body: "test3"}, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"},{"k":"2","h":"76e8644d57eabcb1b39ae54908855de7bb6b53426f1519d88e772e16a18112ce"}]}`, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"},{"k":"2","h":"76e8644d57eabcb1b39ae54908855de7bb6b53426f1519d88e772e16a18112ce"},{"k":"3","h":"d0b3bd259bb16568511cc24e41411895c16a58a579f00d9c8638b724c39824d0"}]}`) + + put("2", + CachedStoreTestType{ID: "2", Body: "test2-updated"}, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"},{"k":"2","h":"76e8644d57eabcb1b39ae54908855de7bb6b53426f1519d88e772e16a18112ce"},{"k":"3","h":"d0b3bd259bb16568511cc24e41411895c16a58a579f00d9c8638b724c39824d0"}]}`, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"},{"k":"2","h":"8e72172076018bcaf12a91703674fc1fc9ab907d0f805a89d52f513bf95fca00"},{"k":"3","h":"d0b3bd259bb16568511cc24e41411895c16a58a579f00d9c8638b724c39824d0"}]}`) + + delete("2", + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"},{"k":"2","h":"8e72172076018bcaf12a91703674fc1fc9ab907d0f805a89d52f513bf95fca00"},{"k":"3","h":"d0b3bd259bb16568511cc24e41411895c16a58a579f00d9c8638b724c39824d0"}]}`, + `{"Data":[{"k":"1","h":"a74d512a5bc25ef815367c51c2bfa7535d1d73079fd9909f4a7d2ef4d256ff22"},{"k":"3","h":"d0b3bd259bb16568511cc24e41411895c16a58a579f00d9c8638b724c39824d0"}]}`) + }) +} diff --git a/server/store/cached_simple.go b/server/store/cached_simple.go new file mode 100644 index 000000000..37186a382 --- /dev/null +++ b/server/store/cached_simple.go @@ -0,0 +1,233 @@ +// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +package store + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "strings" + "sync" + + "github.com/pkg/errors" + + "github.com/mattermost/mattermost-plugin-apps/server/config" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +type SimpleCachedStore[T Cloneable[T]] struct { + cache *sync.Map // of *IndexEntry[T] + api config.API + name string +} + +func MakeSimpleCachedStore[T Cloneable[T]](name string, api config.API, log utils.Logger) (*SimpleCachedStore[T], error) { + s := &SimpleCachedStore[T]{ + cache: &sync.Map{}, + name: name, + api: api, + } + + index, _, _, err := s.syncFromKVDetailed() + if err != nil { + return nil, errors.Wrapf(err, "failed to initialize a cached store %s from KV", s.name) + } + log.Debugf("initialized cached store: %s, %v items", s.name, len(index.Data)) + return s, nil +} + +func (s *SimpleCachedStore[T]) Index() CachedIndex[T] { + out := CachedIndex[T]{} + s.cache.Range(func(key, mapv interface{}) bool { + entry := mapv.(*CachedIndexEntry[T]) + out[entry.Key] = entry + return true + }) + return out +} + +func (s *SimpleCachedStore[T]) getEntry(key string) *CachedIndexEntry[T] { + mapv, _ := s.cache.Load(key) + if mapv == nil { + return nil + } + return mapv.(*CachedIndexEntry[T]) +} + +func (s *SimpleCachedStore[T]) Get(key string) *T { + entry := s.getEntry(key) + if entry == nil { + return nil + } + return entry.data +} + +// update returns nil for newIndex if there was no change +func (s *SimpleCachedStore[T]) Put(r *incoming.Request, key string, value *T) error { + _, _, err := s.update(r, true, key, value) + return err +} + +func (s *SimpleCachedStore[T]) update(r *incoming.Request, persist bool, key string, value *T) (updated *StoredIndex[T], changed bool, err error) { + var rollbacks []func() + defer func() { + if err != nil { + for i := len(rollbacks) - 1; i >= 0; i-- { + rollbacks[i]() + } + err = errors.Wrapf(err, "failed to update cached store %s, rolled back", key) + } + }() + + prev := s.Index().Stored() + prevEntry := s.getEntry(key) + var newEntry *CachedIndexEntry[T] + if value == nil { + if prevEntry == nil { + // No change. + return prev, false, nil + } + + if persist { + err = s.deleteItem(key) + if err != nil { + return nil, false, errors.Wrap(err, "failed to delete item") + } + rollbacks = append(rollbacks, func() { + _ = s.persistItem(key, prevEntry.data) + }) + } + } else { + valueHash := valueHash(value) + if prevEntry != nil && prevEntry.ValueHash == valueHash { + // No change. + return prev, false, nil + } + + if persist { + err = s.persistItem(key, value) + if err != nil { + return nil, false, errors.Wrap(err, "failed to persist item") + } + rollbacks = append(rollbacks, func() { + if prevEntry != nil { + _ = s.persistItem(key, prevEntry.data) + } else { + _ = s.deleteItem(key) + } + }) + } + + newEntry = &CachedIndexEntry[T]{ + Key: key, + ValueHash: valueHash, + data: value, + } + } + + s.updateCachedValue(key, newEntry) + rollbacks = append(rollbacks, func() { s.updateCachedValue(key, prevEntry) }) + + stored := s.Index().Stored() + if persist { + if err = s.persistIndex(stored); err != nil { + return nil, false, errors.Wrap(err, "failed to persist index") + } + rollbacks = append(rollbacks, func() { _ = s.persistIndex(prev) }) + } + + return stored, true, nil +} + +func (s *SimpleCachedStore[T]) updateCachedValue(key string, value *CachedIndexEntry[T]) { + if value != nil { + s.cache.Store(key, value) + } else { + s.cache.Delete(key) + } +} + +func (s *SimpleCachedStore[T]) syncFromKV() error { + _, _, _, err := s.syncFromKVDetailed() + return err +} + +func (s *SimpleCachedStore[T]) syncFromKVDetailed() (stored *StoredIndex[T], changed, removed []CachedIndexEntry[T], err error) { + stored = &StoredIndex[T]{} + err = s.api.Mattermost.KV.Get(s.indexKey(), stored) + if err != nil { + return nil, nil, nil, err + } + + // compare the current cache with the index, update to match + changed, removed = s.Index().Stored().compareTo(stored) + if len(changed) == 0 && len(removed) == 0 { + return stored, changed, removed, nil + } + + for _, entry := range removed { + s.cache.Delete(entry.Key) + } + for _, entry := range changed { + entry.data, err = s.getItem(entry.Key) + if err != nil { + return nil, nil, nil, err + } + + storableClone := entry + s.cache.Store(entry.Key, &storableClone) + } + + return stored, changed, removed, nil +} + +func (s *SimpleCachedStore[T]) indexKey() string { + return fmt.Sprintf("%s.%s-index", CachedPrefix, s.name) +} + +func (s *SimpleCachedStore[T]) itemKey(key string) string { + return fmt.Sprintf("%s.%s-item-%s", CachedPrefix, s.name, key) +} + +func (s *SimpleCachedStore[T]) persistIndex(index *StoredIndex[T]) error { + _, err := s.api.Mattermost.KV.Set(s.indexKey(), index) + return err +} + +func (s *SimpleCachedStore[T]) persistItem(key string, value *T) error { + _, err := s.api.Mattermost.KV.Set(s.itemKey(key), value) + return err +} + +func (s *SimpleCachedStore[T]) deleteItem(key string) error { + return s.api.Mattermost.KV.Delete(s.itemKey(key)) +} + +func (s *SimpleCachedStore[T]) getItem(key string) (*T, error) { + var v T + err := s.api.Mattermost.KV.Get(s.itemKey(key), &v) + return &v, err +} + +func parseCachedStoreKey(key string) (name, id string, err error) { + parts := strings.SplitN(key, "-", 3) + if len(parts) != 3 { + return "", "", errors.Wrap(utils.ErrInvalid, "cached store item key: "+key) + } + + id = parts[2] + parts = strings.Split(parts[0], ".") + if len(parts) != 3 || parts[0] != "" || "."+parts[1] != CachedPrefix { + return "", "", errors.Wrap(utils.ErrInvalid, "cached store item key: "+key) + } + name = parts[2] + + return name, id, nil +} + +func valueHash(value any) string { + data, _ := json.Marshal(value) + return fmt.Sprintf("%x", sha256.Sum256(data)) +} diff --git a/server/store/cached_single_writer.go b/server/store/cached_single_writer.go new file mode 100644 index 000000000..c8efb2ed0 --- /dev/null +++ b/server/store/cached_single_writer.go @@ -0,0 +1,170 @@ +// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +package store + +import ( + "encoding/json" + "sync" + "time" + + "github.com/mattermost/mattermost-server/v6/model" + "github.com/pkg/errors" + + "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +// SingleWriterCachedStore is a CachedStore that ensures only the cluster leader +// node is writing to the KV store. If the request to modify the store +// originates on a non-leader node, it broadcasts a [CachedStoreClusterEvent] to +// all other nodes, including the leader which persists the data. The leader +// then broadcasts the updated index SHA to all other nodes that can re-load +// from KV if out of sync. +type SingleWriterCachedStore[T Cloneable[T]] struct { + *SimpleCachedStore[T] + cluster *CachedStoreCluster + + notifyTimerMutex *sync.Mutex + notifyTimer *time.Timer +} + +func MakeSingleWriterCachedStore[T Cloneable[T]](name string, c *CachedStoreCluster, log utils.Logger) (CachedStore[T], error) { + base, err := MakeSimpleCachedStore[T](name, c.api, log) + if err != nil { + return nil, err + } + s := &SingleWriterCachedStore[T]{ + SimpleCachedStore: base, + cluster: c, + notifyTimerMutex: &sync.Mutex{}, + } + + c.setEventHandler(s.getPutEventID(), s.onPutEvent) + c.setEventHandler(s.getSyncEventID(), s.onSyncEvent) + + return s, nil +} + +const syncBroadcastDelay = 500 * time.Millisecond + +func (s *SingleWriterCachedStore[T]) broadcastSyncLater(r *incoming.Request, hash string) { + s.notifyTimerMutex.Lock() + defer s.notifyTimerMutex.Unlock() + + if s.notifyTimer != nil { + s.notifyTimer.Stop() + } + r = r.Clone() + s.notifyTimer = time.AfterFunc(syncBroadcastDelay, func() { + s.cluster.broadcastEvent(r, s.getSyncEventID(), s.newSyncEvent(hash)) + }) +} + +func (s *SingleWriterCachedStore[T]) notifyOthersOnPut(r *incoming.Request, isOrigin, isLeader bool, key string, value *T, newIndexSHA string) { + // The host that originated the change broadcasts the new data to + // everyone else. + if isOrigin { + s.cluster.broadcastEvent(r, s.getPutEventID(), s.newPutEvent(key, value, newIndexSHA)) + } + + // The host that persisted the data broadcasts the new index hash + // for others to ensure consistency. + if isLeader { + s.broadcastSyncLater(r, newIndexSHA) + } +} + +func (s *SingleWriterCachedStore[T]) Put(r *incoming.Request, key string, value *T) error { + isLeader := r.Config.IsClusterLeader() + isOrigin := true + + index, changed, err := s.SimpleCachedStore.update(r, isLeader, key, value) + if !changed { + return err + } + + s.notifyOthersOnPut(r, isOrigin, isLeader, key, value, index.hash()) + return nil +} + +func (s *SingleWriterCachedStore[T]) getPutEventID() string { + return putEventID + "/" + s.name +} + +func (s *SingleWriterCachedStore[T]) getSyncEventID() string { + return syncEventID + "/" + s.name +} + +func (s *SingleWriterCachedStore[T]) onPutEvent(r *incoming.Request, ev model.PluginClusterEvent) error { + event := cachedStoreClusterEvent[T]{} + err := json.Unmarshal(ev.Data, &event) + if err != nil { + return errors.Wrap(err, "failed to unmarshal cached store cluster event") + } + if event.Key == "" { + return utils.NewInvalidError("key is empty") + } + isClusterLeader := r.Config.IsClusterLeader() + // r.Log.Debugf("received cluster event: PUT %s: %s; new index hash: `%s`, isClusterLeader: %t", + // s.name, event.Key, utils.FirstN(event.IndexHash, 10), isClusterLeader) + + if !isClusterLeader { + // if not the leader, update the in-memory local cache only. + _, _, err = s.SimpleCachedStore.update(r, false, event.Key, event.Value) + return err + } + + index, changed, err := s.SimpleCachedStore.update(r, true, event.Key, event.Value) + if !changed { + return err + } + + s.notifyOthersOnPut(r, false, isClusterLeader, event.Key, event.Value, index.hash()) + return nil +} + +func (s *SingleWriterCachedStore[T]) onSyncEvent(r *incoming.Request, ev model.PluginClusterEvent) error { + event := cachedStoreClusterEvent[T]{} + err := json.Unmarshal(ev.Data, &event) + if err != nil { + return errors.Wrap(err, "failed to unmarshal cached store cluster event") + } + isClusterLeader := r.Config.IsClusterLeader() + r.Log.Debugf("received cluster event SYNC %s: %s; new index hash: `%s`, isClusterLeader: %t", + s.name, event.Key, utils.FirstN(event.IndexHash, 10), isClusterLeader) + if isClusterLeader { + return errors.New("cluster leader should not receive sync events") + } + if event.IndexHash == "" { + return utils.NewInvalidError("IndexHash is empty") + } + + if event.IndexHash != s.Index().Stored().hash() { + r.Log.Debugf("SingleWriterCachedStore.processClusterEvent %s: index hash mismatch, syncing from KV", s.name) + updated, _, _, err := s.syncFromKVDetailed() + if err != nil { + return err + } + if event.IndexHash != updated.hash() { + return errors.Errorf("index hash mismatch after sync: `%s`, expected `%s`", event.IndexHash, updated.hash()) + } + } + return nil +} + +func (s *SingleWriterCachedStore[T]) newPutEvent(key string, data *T, indexHash string) cachedStoreClusterEvent[T] { + return cachedStoreClusterEvent[T]{ + Value: data, + Key: key, + StoreName: s.name, + IndexHash: indexHash, + } +} + +func (s *SingleWriterCachedStore[T]) newSyncEvent(indexHash string) cachedStoreClusterEvent[T] { + return cachedStoreClusterEvent[T]{ + StoreName: s.name, + IndexHash: indexHash, + } +} diff --git a/server/store/cached_test.go b/server/store/cached_test.go new file mode 100644 index 000000000..14a7baa08 --- /dev/null +++ b/server/store/cached_test.go @@ -0,0 +1,37 @@ +package store + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestStoredIndexCompareTo(t *testing.T) { + v1 := 1 + v2 := 2 + v3 := 3 + v5 := 5 + before := StoredIndex[int]{ + Data: []CachedIndexEntry[int]{ + {Key: "key1", ValueHash: "hash1", data: &v1}, + {Key: "key2", ValueHash: "hash2", data: &v2}, + {Key: "key3", ValueHash: "hash3", data: &v3}, + }, + } + after := StoredIndex[int]{ + Data: []CachedIndexEntry[int]{ + {Key: "key1", ValueHash: "hash1", data: &v1}, + {Key: "key3", ValueHash: "hash5", data: &v5}, + {Key: "key4", ValueHash: "hash4", data: &v3}, + }, + } + + change, remove := before.compareTo(&after) + require.Equal(t, []CachedIndexEntry[int]{ + {Key: "key2", ValueHash: "hash2", data: &v2}, + }, remove) + require.Equal(t, []CachedIndexEntry[int]{ + {Key: "key3", ValueHash: "hash5", data: &v5}, + {Key: "key4", ValueHash: "hash4", data: &v3}, + }, change) +} diff --git a/server/store/cached_test_memory_store.go b/server/store/cached_test_memory_store.go new file mode 100644 index 000000000..da7bebc70 --- /dev/null +++ b/server/store/cached_test_memory_store.go @@ -0,0 +1,47 @@ +// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +package store + +import ( + "github.com/mattermost/mattermost-plugin-apps/apps" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" + "github.com/mattermost/mattermost-plugin-apps/utils" +) + +type TestingCachedStore[T Cloneable[T]] map[string]T + +var _ CachedStore[apps.App] = (TestingCachedStore[apps.App])(nil) + +func MakeTestCachedStore[T Cloneable[T]](name string, c *CachedStoreCluster, log utils.Logger) (CachedStore[T], error) { + return TestingCachedStore[T]{}, nil +} + +func (s TestingCachedStore[T]) Get(key string) *T { + value, ok := s[key] + if ok { + return &value + } + return nil +} + +func (s TestingCachedStore[T]) Put(r *incoming.Request, key string, value *T) error { + if value != nil { + s[key] = *value + } else { + delete(s, key) + } + return nil +} + +func (s TestingCachedStore[T]) Index() CachedIndex[T] { + out := CachedIndex[T]{} + for key, value := range s { + out[key] = &CachedIndexEntry[T]{ + Key: key, + ValueHash: valueHash(value), + data: value.Clone(), + } + } + return out +} diff --git a/server/store/kv_debug_info.go b/server/store/kv_debug_info.go index 6a5220f66..536b49e8b 100644 --- a/server/store/kv_debug_info.go +++ b/server/store/kv_debug_info.go @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" "github.com/mattermost/mattermost-plugin-apps/apps" - "github.com/mattermost/mattermost-plugin-apps/utils" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" ) type KVDebugAppInfo struct { @@ -25,15 +25,14 @@ func (i KVDebugAppInfo) Total() int { } type KVDebugInfo struct { - InstalledAppCount int - Apps map[apps.AppID]*KVDebugAppInfo - AppsTotal int - ManifestCount int - OAuth2StateCount int - Other int - SubscriptionCount int - Total int - Debug int + Apps map[apps.AppID]*KVDebugAppInfo + AppsTotal int + CachedStoreTotal int + CachedStoreCountByName map[string]int + Debug int + OAuth2StateCount int + Other int + Total int } func (i KVDebugInfo) forAppID(appID apps.AppID) *KVDebugAppInfo { @@ -49,12 +48,13 @@ func (i KVDebugInfo) forAppID(appID apps.AppID) *KVDebugAppInfo { return appInfo } -func (s *Service) GetDebugKVInfo(log utils.Logger) (*KVDebugInfo, error) { +func GetKVDebugInfo(r *incoming.Request) (*KVDebugInfo, error) { info := KVDebugInfo{ - Apps: map[apps.AppID]*KVDebugAppInfo{}, + Apps: map[apps.AppID]*KVDebugAppInfo{}, + CachedStoreCountByName: map[string]int{}, } for i := 0; ; i++ { - keys, err := s.conf.API().Mattermost.KV.ListKeys(i, ListKeysPerPage) + keys, err := r.API.Mattermost.KV.ListKeys(i, ListKeysPerPage) if err != nil { return nil, errors.Wrapf(err, "failed to list keys - page, %d", i) } @@ -70,13 +70,13 @@ func (s *Service) GetDebugKVInfo(log utils.Logger) (*KVDebugInfo, error) { appInfo := info.forAppID(appID) isHashKey = true switch gns { - case KVAppPrefix: + case KVPrefix: appInfo.AppKVCount++ appInfo.AppKVCountByNamespace[ns]++ appInfo.AppKVCountByUserID[userID]++ info.AppsTotal++ - case KVUserPrefix: + case UserPrefix: appInfo.UserCount++ info.AppsTotal++ @@ -89,10 +89,7 @@ func (s *Service) GetDebugKVInfo(log utils.Logger) (*KVDebugInfo, error) { } switch { - case strings.HasPrefix(key, KVSubPrefix): - info.SubscriptionCount++ - - case strings.HasPrefix(key, KVTokenPrefix): + case strings.HasPrefix(key, TokenPrefix): appID, _, err := parseSessionKey(key) if err != nil { continue @@ -100,19 +97,20 @@ func (s *Service) GetDebugKVInfo(log utils.Logger) (*KVDebugInfo, error) { info.forAppID(appID).TokenCount++ info.AppsTotal++ - case strings.HasPrefix(key, KVOAuth2StatePrefix): + case strings.HasPrefix(key, OAuth2StatePrefix): info.OAuth2StateCount++ - case strings.HasPrefix(key, KVInstalledAppPrefix): - info.InstalledAppCount++ - - case strings.HasPrefix(key, KVLocalManifestPrefix): - info.ManifestCount++ + case strings.HasPrefix(key, CachedPrefix): + name, _, _ := parseCachedStoreKey(key) + if name != "" { + info.CachedStoreCountByName[name]++ + } + info.CachedStoreTotal++ case key == "mmi_botid": info.Other++ - case strings.HasPrefix(key, KVDebugPrefix): + case strings.HasPrefix(key, DebugPrefix): info.Debug++ } } diff --git a/server/store/manifest.go b/server/store/manifest.go index da26ceaa3..9823e6246 100644 --- a/server/store/manifest.go +++ b/server/store/manifest.go @@ -4,14 +4,11 @@ package store import ( - "context" - "crypto/sha1" // nolint:gosec + "context" // nolint:gosec "encoding/json" - "fmt" "os" "path/filepath" "strings" - "sync" "github.com/pkg/errors" @@ -23,83 +20,47 @@ import ( "github.com/mattermost/mattermost-plugin-apps/utils" ) -type ManifestStore interface { - config.Configurable - - StoreLocal(*incoming.Request, apps.Manifest) error - Get(apps.AppID) (*apps.Manifest, error) - GetFromS3(appID apps.AppID, version apps.AppVersion) (*apps.Manifest, error) - AsMap() map[apps.AppID]apps.Manifest - DeleteLocal(*incoming.Request, apps.AppID) error +type ManifestStore struct { + CachedStore[apps.Manifest] + catalog map[apps.AppID]apps.Manifest + svc *Service } -// manifestStore combines global (aka marketplace) manifests, and locally -// installed ones. The global list is loaded on startup. The local manifests are -// stored in KV store, and the list of their keys is stored in the config, as a -// map of AppID->sha1(manifest). -type manifestStore struct { - *Service - - // mutex guards local, the pointer to the map of locally-installed - // manifests. - mutex sync.RWMutex - - global map[apps.AppID]apps.Manifest - local map[apps.AppID]apps.Manifest - - aws upaws.Client - s3AssetBucket string +func (s *Service) makeManifestStore(log utils.Logger) (*ManifestStore, error) { + cached, err := MakeCachedStore[apps.Manifest](ManifestStoreName, s.cluster, log) + if err != nil { + return nil, err + } + return &ManifestStore{ + CachedStore: cached, + svc: s, + }, nil } -var _ ManifestStore = (*manifestStore)(nil) - -func (s *Service) makeManifestStore() (*manifestStore, error) { - conf := s.conf.Get() - log := s.conf.NewBaseLogger().With("purpose", "Manifest store") +func (s *ManifestStore) InitCloudCatalog(confService config.Service, httpOut httpout.Service) error { + conf := confService.Get() + log := confService.NewBaseLogger() awsClient, err := upaws.MakeClient(conf.AWSAccessKey, conf.AWSSecretKey, conf.AWSRegion, log) if err != nil { - return nil, errors.Wrap(err, "failed to initialize AWS access") + return errors.Wrap(err, "failed to initialize AWS access") } - mstore := &manifestStore{ - Service: s, - aws: awsClient, - s3AssetBucket: conf.AWSS3Bucket, - } - if err = mstore.Configure(log); err != nil { - return nil, errors.Wrap(err, "failed to configure") - } - - if conf.MattermostCloudMode { - err = mstore.InitGlobal(s.httpOut, log) - if err != nil { - return nil, errors.Wrap(err, "failed to initialize the global manifest list from marketplace") - } - } - return mstore, nil -} - -// InitGlobal reads in the list of known (i.e. marketplace listed) app -// manifests. -func (s *manifestStore) InitGlobal(httpOut httpout.Service, log utils.Logger) error { - conf := s.conf.Get() - - bundlePath, err := s.conf.API().Mattermost.System.GetBundlePath() + bundlePath, err := confService.API().Mattermost.System.GetBundlePath() if err != nil { - return errors.Wrap(err, "can't get bundle path") + return errors.Wrap(err, "can't get bundle path for global catalog of apps") } assetPath := filepath.Join(bundlePath, "assets") f, err := os.Open(filepath.Join(assetPath, config.ManifestsFile)) if err != nil { - return errors.Wrap(err, "failed to load global list of available apps") + return errors.Wrap(err, "failed to load global catalog of apps") } defer f.Close() - global := map[apps.AppID]apps.Manifest{} + catalog := map[apps.AppID]apps.Manifest{} manifestLocations := map[apps.AppID]string{} err = json.NewDecoder(f).Decode(&manifestLocations) if err != nil { - return err + return errors.Wrap(err, "failed to decode global catalog of apps") } var data []byte @@ -107,9 +68,9 @@ func (s *manifestStore) InitGlobal(httpOut httpout.Service, log utils.Logger) er parts := strings.SplitN(loc, ":", 2) switch { case len(parts) == 1: - data, err = s.getDataFromS3(appID, apps.AppVersion(parts[0])) + data, err = getManifestFromS3(awsClient, conf.AWSS3Bucket, appID, apps.AppVersion(parts[0])) case len(parts) == 2 && parts[0] == "s3": - data, err = s.getDataFromS3(appID, apps.AppVersion(parts[1])) + data, err = getManifestFromS3(awsClient, conf.AWSS3Bucket, appID, apps.AppVersion(parts[1])) case len(parts) == 2 && parts[0] == "file": data, err = os.ReadFile(filepath.Join(assetPath, parts[1])) case len(parts) == 2 && (parts[0] == "http" || parts[0] == "https"): @@ -140,196 +101,47 @@ func (s *manifestStore) InitGlobal(httpOut httpout.Service, log utils.Logger) er "loc", loc) continue } - global[appID] = *m + catalog[appID] = *m } - - s.mutex.Lock() - s.global = global - s.mutex.Unlock() - + s.catalog = catalog return nil } -func (s *manifestStore) Configure(log utils.Logger) error { - updatedLocal := map[apps.AppID]apps.Manifest{} - - for id, key := range s.conf.Get().LocalManifests { - log = log.With("app_id", id) - - var data []byte - err := s.conf.API().Mattermost.KV.Get(KVLocalManifestPrefix+key, &data) - if err != nil { - log.WithError(err).Errorw("Failed to get local manifest from KV") - continue - } - - if len(data) == 0 { - err = utils.NewNotFoundError(KVLocalManifestPrefix + key) - log.WithError(err).Errorw("Failed to load local manifest") - continue - } - - m, err := apps.DecodeCompatibleManifest(data) - if err != nil { - log.WithError(err).Errorw("Failed to decode local manifest") - continue - } - updatedLocal[apps.AppID(id)] = *m +func (s *ManifestStore) Get(appID apps.AppID) (*apps.Manifest, error) { + m := s.CachedStore.Get(string(appID)) + if m != nil { + return m, nil } - - s.mutex.Lock() - s.local = updatedLocal - s.mutex.Unlock() - return nil -} - -func (s *manifestStore) Get(appID apps.AppID) (*apps.Manifest, error) { - s.mutex.RLock() - local := s.local - global := s.global - s.mutex.RUnlock() - - m, ok := local[appID] + listed, ok := s.catalog[appID] if ok { - return &m, nil - } - m, ok = global[appID] - if ok { - return &m, nil + return &listed, nil } return nil, errors.Wrap(utils.ErrNotFound, string(appID)) } -func (s *manifestStore) AsMap() map[apps.AppID]apps.Manifest { - s.mutex.RLock() - local := s.local - global := s.global - s.mutex.RUnlock() - +func (s *ManifestStore) AsMap() map[apps.AppID]apps.Manifest { out := map[apps.AppID]apps.Manifest{} - for id, m := range global { - out[id] = m + for appID, m := range s.catalog { + out[appID] = m } - for id, m := range local { - out[id] = m - } - return out -} - -func (s *manifestStore) StoreLocal(r *incoming.Request, m apps.Manifest) error { - conf := s.conf.Get() - mm := s.conf.API().Mattermost - prevSHA := conf.LocalManifests[string(m.AppID)] - - m.SchemaVersion = conf.PluginManifest.Version - data, err := json.Marshal(m) - if err != nil { - return err - } - sha := fmt.Sprintf("%x", sha1.Sum(data)) // nolint:gosec - _, err = mm.KV.Set(KVLocalManifestPrefix+sha, m) - if err != nil { - return err - } - - s.mutex.RLock() - local := s.local - s.mutex.RUnlock() - updatedLocal := map[apps.AppID]apps.Manifest{} - for k, v := range local { - if k != m.AppID { - updatedLocal[k] = v - } - } - updatedLocal[m.AppID] = m - s.mutex.Lock() - s.local = updatedLocal - s.mutex.Unlock() - - updated := map[string]string{} - for k, v := range conf.LocalManifests { - updated[k] = v - } - updated[string(m.AppID)] = sha - sc := conf.StoredConfig - sc.LocalManifests = updated - err = s.conf.StoreConfig(sc, r.Log) - if err != nil { - return err - } - - if sha != prevSHA { - err = mm.KV.Delete(KVLocalManifestPrefix + prevSHA) - if err != nil { - r.Log.WithError(err).Warnf("Failed to delete previous Manifest KV value") - } - } - return nil -} - -func (s *manifestStore) DeleteLocal(r *incoming.Request, appID apps.AppID) error { - conf := s.conf.Get() - sha := conf.LocalManifests[string(appID)] - - err := s.conf.API().Mattermost.KV.Delete(KVLocalManifestPrefix + sha) - if err != nil { - return err - } - - s.mutex.RLock() - local := s.local - s.mutex.RUnlock() - updatedLocal := map[apps.AppID]apps.Manifest{} - for k, v := range local { - if k != appID { - updatedLocal[k] = v + for id := range s.Index() { + if m := s.CachedStore.Get(id); m != nil { + out[apps.AppID(id)] = *m.Clone() } } - s.mutex.Lock() - s.local = updatedLocal - s.mutex.Unlock() - - updated := map[string]string{} - for k, v := range conf.LocalManifests { - updated[k] = v - } - delete(updated, string(appID)) - sc := conf.StoredConfig - sc.LocalManifests = updated - - return s.conf.StoreConfig(sc, r.Log) + return out } -// getFromS3 returns manifest data for an app from the S3 -func (s *manifestStore) getDataFromS3(appID apps.AppID, version apps.AppVersion) ([]byte, error) { +// getManifestFromS3 returns manifest data for an app from the S3 +func getManifestFromS3(aws upaws.Client, bucket string, appID apps.AppID, version apps.AppVersion) ([]byte, error) { name := upaws.S3ManifestName(appID, version) - data, err := s.aws.GetS3(context.Background(), s.s3AssetBucket, name) + data, err := aws.GetS3(context.Background(), bucket, name) if err != nil { return nil, errors.Wrapf(err, "failed to download manifest %s", name) } - return data, nil } -// GetFromS3 returns the manifest for an app from the S3 -func (s *manifestStore) GetFromS3(appID apps.AppID, version apps.AppVersion) (*apps.Manifest, error) { - data, err := s.getDataFromS3(appID, version) - if err != nil { - return nil, errors.Wrap(err, "failed to get manifest data") - } - - m, err := apps.DecodeCompatibleManifest(data) - if err != nil { - return nil, errors.Wrap(err, "failed to marshal manifest data") - } - - if m.AppID != appID { - return nil, errors.New("mismatched app ID") - } - - if m.Version != version { - return nil, errors.New("mismatched app version") - } - - return m, nil +func (s *ManifestStore) Save(r *incoming.Request, m apps.Manifest) error { + return s.CachedStore.Put(r, string(m.AppID), &m) } diff --git a/server/store/migration.go b/server/store/migration.go new file mode 100644 index 000000000..415b6d935 --- /dev/null +++ b/server/store/migration.go @@ -0,0 +1,19 @@ +package store + +type StoredConfigV1_2 struct { + // InstalledApps is a list of all apps installed on the Mattermost instance. + // + // For each installed app, an entry of string(AppID) -> sha1(App) is added, + // and the App struct is stored in KV under app_. Implementation + // in `store.App`. + InstalledApps map[string]string `json:"installed_apps,omitempty"` + + // LocalManifests is a list of locally-stored manifests. Local is in + // contrast to the "global" list of manifests which in the initial version + // is loaded from S3. + // + // For each installed app, an entry of string(AppID) -> sha1(Manifest) is + // added, and the Manifest struct is stored in KV under + // manifest_. Implementation in `store.Manifest`. + LocalManifests map[string]string `json:"local_manifests,omitempty"` +} diff --git a/server/store/oauth2.go b/server/store/oauth2.go index 895e6928e..615ca3bce 100644 --- a/server/store/oauth2.go +++ b/server/store/oauth2.go @@ -12,45 +12,34 @@ import ( pluginapi "github.com/mattermost/mattermost-plugin-api" - "github.com/mattermost/mattermost-plugin-apps/apps" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" "github.com/mattermost/mattermost-plugin-apps/utils" ) -type OAuth2Store interface { - CreateState(actingUserID string) (string, error) - ValidateStateOnce(urlState, actingUserID string) error - SaveUser(appID apps.AppID, actingUserID string, data []byte) error - GetUser(appID apps.AppID, actingUserID string) ([]byte, error) -} - -type oauth2Store struct { - *Service -} - -var _ OAuth2Store = (*oauth2Store)(nil) +type OAuth2Store struct{} -func (s *oauth2Store) CreateState(actingUserID string) (string, error) { +func (s *OAuth2Store) CreateState(r *incoming.Request) (string, error) { // fit the max key size of ~50chars buf := make([]byte, 15) _, _ = rand.Read(buf) - state := fmt.Sprintf("%s.%s", base64.RawURLEncoding.EncodeToString(buf), actingUserID) - _, err := s.conf.API().Mattermost.KV.Set(KVOAuth2StatePrefix+state, state, pluginapi.SetExpiry(15*time.Minute)) + state := fmt.Sprintf("%s.%s", base64.RawURLEncoding.EncodeToString(buf), r.ActingUserID()) + _, err := r.API.Mattermost.KV.Set(OAuth2StatePrefix+state, state, pluginapi.SetExpiry(15*time.Minute)) if err != nil { return "", err } return state, nil } -func (s *oauth2Store) ValidateStateOnce(urlState, actingUserID string) error { +func (s *OAuth2Store) ValidateStateOnce(r *incoming.Request, urlState string) error { ss := strings.Split(urlState, ".") - if len(ss) != 2 || ss[1] != actingUserID { + if len(ss) != 2 || ss[1] != r.ActingUserID() { return utils.ErrForbidden } storedState := "" - key := KVOAuth2StatePrefix + urlState - err := s.conf.API().Mattermost.KV.Get(key, &storedState) - _ = s.conf.API().Mattermost.KV.Delete(key) + key := OAuth2StatePrefix + urlState + err := r.API.Mattermost.KV.Get(key, &storedState) + _ = r.API.Mattermost.KV.Delete(key) if err != nil { return err } @@ -61,32 +50,32 @@ func (s *oauth2Store) ValidateStateOnce(urlState, actingUserID string) error { return nil } -func (s *oauth2Store) SaveUser(appID apps.AppID, actingUserID string, data []byte) error { - if appID == "" || actingUserID == "" { +func (s *OAuth2Store) SaveUser(r *incoming.Request, data []byte) error { + if r.SourceAppID() == "" || r.ActingUserID() == "" { return utils.NewInvalidError("app and user IDs must be provided") } - userkey, err := Hashkey(KVUserPrefix, appID, actingUserID, "", KVUserKey) + userkey, err := Hashkey(UserPrefix, r.SourceAppID(), r.ActingUserID(), "", OAuth2UserKey) if err != nil { return err } - _, err = s.conf.API().Mattermost.KV.Set(userkey, data) + _, err = r.API.Mattermost.KV.Set(userkey, data) return err } -func (s *oauth2Store) GetUser(appID apps.AppID, actingUserID string) ([]byte, error) { - if appID == "" || actingUserID == "" { +func (s *OAuth2Store) GetUser(r *incoming.Request) ([]byte, error) { + if r.SourceAppID() == "" || r.ActingUserID() == "" { return nil, utils.NewInvalidError("app and user IDs must be provided") } - userkey, err := Hashkey(KVUserPrefix, appID, actingUserID, "", KVUserKey) + userkey, err := Hashkey(UserPrefix, r.SourceAppID(), r.ActingUserID(), "", OAuth2UserKey) if err != nil { return nil, err } var data []byte - if err = s.conf.API().Mattermost.KV.Get(userkey, &data); err != nil { + if err = r.API.Mattermost.KV.Get(userkey, &data); err != nil { return nil, err } diff --git a/server/store/oauth2_test.go b/server/store/oauth2_test.go index 3d97b29a7..2e2a93474 100644 --- a/server/store/oauth2_test.go +++ b/server/store/oauth2_test.go @@ -11,62 +11,61 @@ import ( "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-plugin-apps/apps" "github.com/mattermost/mattermost-plugin-apps/server/config" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" ) func TestCreateOAuth2State(t *testing.T) { stateRE := `[A-Za-z0-9-_]+\.[A-Za-z0-9]` userID := `userid-test` conf, api := config.NewTestService(nil) - s := oauth2Store{ - Service: &Service{ - conf: conf, - }, - } + s := OAuth2Store{} // CreateState api.On("KVSetWithOptions", mock.Anything, mock.Anything, mock.Anything).Once().Run(func(args mock.Arguments) { - require.Regexp(t, KVOAuth2StatePrefix+stateRE, args.String(0)) + require.Regexp(t, OAuth2StatePrefix+stateRE, args.String(0)) data, _ := args.Get(1).([]byte) require.Regexp(t, stateRE, string(data)) }).Return(true, nil) - urlState, err := s.CreateState(userID) + + r := incoming.NewRequest(conf, nil, "test", "reqid").WithActingUserID(userID).WithSourceAppID("some_app_id") + + urlState, err := s.CreateState(r) require.NoError(t, err) - key := KVOAuth2StatePrefix + urlState + key := OAuth2StatePrefix + urlState require.LessOrEqual(t, len(key), model.KeyValueKeyMaxRunes) require.Regexp(t, stateRE, urlState) // Validate errors - err = s.ValidateStateOnce("invalidformat", userID) + err = s.ValidateStateOnce(r, "invalidformat") require.EqualError(t, err, "forbidden") - err = s.ValidateStateOnce("nonexistent.value", userID) + err = s.ValidateStateOnce(r, "nonexistent.value") require.EqualError(t, err, "forbidden") - err = s.ValidateStateOnce(urlState, "idmismatch") + err = s.ValidateStateOnce(r.WithActingUserID("idmismatch"), urlState) require.EqualError(t, err, "forbidden") mismatchedState := "mismatched-random." + strings.Split(urlState, ".")[1] - mismatchedKey := KVOAuth2StatePrefix + mismatchedState + mismatchedKey := OAuth2StatePrefix + mismatchedState api.On("KVGet", mismatchedKey).Once().Return(nil, nil) // not found api.On("KVSetWithOptions", mismatchedKey, []byte(nil), mock.Anything).Once().Return(false, nil) // delete attempt - err = s.ValidateStateOnce(mismatchedState, userID) + err = s.ValidateStateOnce(r, mismatchedState) require.EqualError(t, err, "state mismatch: forbidden") api.On("KVGet", key).Once().Return([]byte(`"`+urlState+`"`), nil) api.On("KVSetWithOptions", key, []byte(nil), mock.Anything).Once().Return(true, nil) // delete - err = s.ValidateStateOnce(urlState, userID) + err = s.ValidateStateOnce(r, urlState) require.NoError(t, err) } func TestOAuth2User(t *testing.T) { userID := "userIDis26bytes12345678910" + appID := apps.AppID("some_app_id") conf, api := config.NewTestService(nil) - s := oauth2Store{ - Service: &Service{ - conf: conf, - }, - } + s := OAuth2Store{} + r := incoming.NewRequest(conf, nil, "test", "reqid").WithActingUserID(userID).WithSourceAppID(appID) type Entity struct { Test1, Test2 string @@ -76,16 +75,16 @@ func TestOAuth2User(t *testing.T) { data := []byte(`{"Test1":"test-1","Test2":"test-2"}`) // CreateState api.On("KVSetWithOptions", key, data, mock.Anything).Return(true, nil).Once() - err := s.SaveUser("some_app_id", userID, data) + err := s.SaveUser(r, data) require.NoError(t, err) api.On("KVGet", key).Return(data, nil).Once() - rData, err := s.GetUser("some_app_id", userID) + rData, err := s.GetUser(r) assert.NoError(t, err) assert.NotNil(t, rData) - var r Entity - err = json.Unmarshal(rData, &r) + var received Entity + err = json.Unmarshal(rData, &received) assert.NoError(t, err) - require.Equal(t, entity, r) + require.Equal(t, entity, received) } diff --git a/server/store/pkg.go b/server/store/pkg.go new file mode 100644 index 000000000..29162fed8 --- /dev/null +++ b/server/store/pkg.go @@ -0,0 +1,13 @@ +// Copyright (c) 2020-present Mattermost, Inc. All Rights Reserved. +// See License for license information. + +// Provides persistent storage capabilities for the apps framework. +// Specifically, stores apps, manifests, subscriptions, and apps data: KV, user, +// and OAUth2 state data. +// +// [CachedStore] provides a cluster-aware write-through in-memory cache for +// Apps, Manifests, and Subscriptions. There are 2 important implementations. To +// ensure the store consistency [MutexCachedStore] which uses a cluster.Mutex, +// and [Sing;eWriterCachedStore] which performs all updates on the cluster +// leader node. +package store diff --git a/server/store/service.go b/server/store/service.go index 9f3ce2647..fa7f5d962 100644 --- a/server/store/service.go +++ b/server/store/service.go @@ -14,7 +14,6 @@ import ( "github.com/mattermost/mattermost-plugin-apps/apps" "github.com/mattermost/mattermost-plugin-apps/server/config" - "github.com/mattermost/mattermost-plugin-apps/server/httpout" "github.com/mattermost/mattermost-plugin-apps/server/incoming" ) @@ -33,83 +32,91 @@ import ( // All other keys must start with an ASCII letter. '.' is usually used as the // terminator since it is not used in the base64 representation. const ( - // KVAppPrefix is the Apps global namespace. - KVAppPrefix = ".k" + // KVPrefix is the global namespace for apps KV data. + KVPrefix = ".k" - // KVUserPrefix is the global namespace used to store user - // records. - KVUserPrefix = ".u" + // UserPrefix is the global namespace used to store user records. + UserPrefix = ".u" - // KVUserPrefix is the key to store OAuth2 user - // records. - KVUserKey = "oauth2_user" + // CachedPrefix is the global namespace for storing synchronized cached + // lists of records like apps and subscriptions. + CachedPrefix = ".cached" - // KVOAuth2StatePrefix is the global namespace used to store OAuth2 - // ephemeral state data. - KVOAuth2StatePrefix = ".o" + // OAuth2StatePrefix is the global namespace used to store OAuth2 ephemeral + // state data. + OAuth2StatePrefix = ".o" - // KVSubPrefix is used for keys storing subscriptions. - KVSubPrefix = "sub." + TokenPrefix = ".t" - // KVInstalledAppPrefix is used to store App records. - KVInstalledAppPrefix = "app." + DebugPrefix = ".debug." - // KVLocalManifestPrefix is used to store locally-listed manifests. - KVLocalManifestPrefix = "man." + // OAuth2UserKey is the key to store OAuth2 user records, in the UserPrefix + // global namespace. There is only one key per user. + OAuth2UserKey = "oauth2_user" - KVTokenPrefix = ".t" - - KVDebugPrefix = ".debug." - - // KVCallOnceKey and KVClusterMutexKey are used for invoking App Calls once, + // CallOnceKey and KVClusterMutexKey are used for invoking App Calls once, // usually upon a Mattermost instance startup. - KVCallOnceKey = "CallOnce" - KVClusterMutexKey = "Cluster_Mutex" + CallOnceKey = "CallOnce" + ClusterMutexKey = "Cluster_Mutex" +) + +const ( + AppStoreName = "apps" + ManifestStoreName = "manifests" + SubscriptionStoreName = "subscriptions" ) const ( ListKeysPerPage = 1000 ) +const ( + hashKeyLength = 82 +) + type Service struct { - App AppStore - Subscription SubscriptionStore - Manifest ManifestStore - AppKV AppKVStore - OAuth2 OAuth2Store - Session SessionStore - - conf config.Service - httpOut httpout.Service + App Apps + Subscription *SubscriptionStore + Manifest *ManifestStore + AppKV *KVStore + OAuth2 *OAuth2Store + Session Sessions + + cluster *CachedStoreCluster } -func MakeService(confService config.Service, httpOut httpout.Service) (*Service, error) { +// MakeService creates and initializes a persistent storage Service. defaultKind +// will be used to make the app, manifest, and subscription stores and specifies +// how they will be replicated across cluster nodes. +func MakeService(conf config.Service, defaultKind CachedStoreClusterKind) (*Service, error) { s := &Service{ - conf: confService, - httpOut: httpOut, + cluster: NewCachedStoreCluster(conf.API(), defaultKind), + AppKV: &KVStore{}, + OAuth2: &OAuth2Store{}, + Session: &SessionStore{}, } - s.AppKV = &appKVStore{Service: s} - s.OAuth2 = &oauth2Store{Service: s} - s.Subscription = &subscriptionStore{Service: s} - s.Session = &sessionStore{Service: s} + log := conf.NewBaseLogger() var err error - s.App, err = s.makeAppStore() + s.App, err = s.makeAppStore(conf.Get().PluginManifest.Version, log) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to initialize the app store") } - - s.Manifest, err = s.makeManifestStore() + s.Manifest, err = s.makeManifestStore(log) + if err != nil { + return nil, errors.Wrap(err, "failed to initialize the manifest store") + } + s.Subscription, err = s.makeSubscriptionStore(log) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to initialize the subscription store") } + return s, nil } -const ( - hashKeyLength = 82 -) - +// Makes a hash key that is used to store data in the KV store, that is specific +// to a given app and user. key is hashed, everything else is preserved in the +// output. func Hashkey(globalNamespace string, appID apps.AppID, userID, appNamespace, key string) (string, error) { gns := []byte(globalNamespace) a := []byte(appID) @@ -137,7 +144,7 @@ func Hashkey(globalNamespace string, appID apps.AppID, userID, appNamespace, key case len(k) == 0: return "", errors.New("key must not be empty") case len(a) != 32: - return "", errors.New("appID must be max length") + return "", errors.New("appID %s is tooo long, must be 32 bytes or fewer") case len(u) != 26: return "", errors.Errorf("userID %q must be exactly 26 ASCII characters", userID) case len(gns) != 2 || gns[0] != '.': @@ -152,19 +159,19 @@ func Hashkey(globalNamespace string, appID apps.AppID, userID, appNamespace, key return hashed, nil } -func hashkey(globalNamespace, appID, userID, appNamespace, id []byte) string { - idHash := make([]byte, 16) - sha3.ShakeSum128(idHash, id) - encodedID := make([]byte, ascii85.MaxEncodedLen(len(idHash))) - _ = ascii85.Encode(encodedID, idHash) - - key := make([]byte, 0, model.KeyValueKeyMaxRunes) - key = append(key, globalNamespace...) - key = append(key, appID...) - key = append(key, userID...) - key = append(key, appNamespace...) - key = append(key, encodedID...) - return string(key) +func hashkey(globalNamespace, appID, userID, appNamespace, key []byte) string { + hash := make([]byte, 16) + sha3.ShakeSum128(hash, key) + encodedID := make([]byte, ascii85.MaxEncodedLen(len(hash))) + _ = ascii85.Encode(encodedID, hash) + + hashed := make([]byte, 0, model.KeyValueKeyMaxRunes) + hashed = append(hashed, globalNamespace...) + hashed = append(hashed, appID...) + hashed = append(hashed, userID...) + hashed = append(hashed, appNamespace...) + hashed = append(hashed, encodedID...) + return string(hashed) } func ParseHashkey(key string) (globalNamespace string, appID apps.AppID, userID, appNamespace, idhash string, err error) { @@ -181,7 +188,7 @@ func ParseHashkey(key string) (globalNamespace string, appID apps.AppID, userID, return string(gns), apps.AppID(strings.TrimSpace(string(a))), string(u), strings.TrimSpace(string(ns)), string(h), nil } -func (s *Service) ListHashKeys( +func ListHashKeys( r *incoming.Request, processf func(key string) error, matchf ...func(prefix string, _ apps.AppID, userID, namespace, idhash string) bool, @@ -220,11 +227,11 @@ func (s *Service) ListHashKeys( } } -func (s *Service) RemoveAllKVAndUserDataForApp(r *incoming.Request, appID apps.AppID) error { - if err := s.ListHashKeys(r, r.API.Mattermost.KV.Delete, WithAppID(appID), WithPrefix(KVAppPrefix)); err != nil { +func RemoveAllKVAndUserDataForApp(r *incoming.Request, appID apps.AppID) error { + if err := ListHashKeys(r, r.API.Mattermost.KV.Delete, WithAppID(appID), WithPrefix(KVPrefix)); err != nil { return errors.Wrap(err, "failed to remove all data for app") } - if err := s.ListHashKeys(r, r.API.Mattermost.KV.Delete, WithAppID(appID), WithPrefix(KVUserPrefix)); err != nil { + if err := ListHashKeys(r, r.API.Mattermost.KV.Delete, WithAppID(appID), WithPrefix(UserPrefix)); err != nil { return errors.Wrap(err, "failed to remove all data for app") } return nil diff --git a/server/store/session.go b/server/store/session.go index 98633736f..21dfc071f 100644 --- a/server/store/session.go +++ b/server/store/session.go @@ -11,28 +11,24 @@ import ( "github.com/mattermost/mattermost-plugin-apps/utils" ) -type SessionStore interface { - Get(_ apps.AppID, userID string) (*model.Session, error) - ListForApp(apps.AppID) ([]*model.Session, error) - ListForUser(_ *incoming.Request, userID string) ([]*model.Session, error) - Save(_ apps.AppID, userID string, session *model.Session) error - Delete(_ apps.AppID, userID string) error +type SessionStore struct{} + +type Sessions interface { + Get(_ *incoming.Request, _ apps.AppID, userID string) (*model.Session, error) + Save(_ *incoming.Request, _ apps.AppID, userID string, session *model.Session) error + ListForUser(r *incoming.Request, userID string) ([]*model.Session, error) + ListForApp(r *incoming.Request, appID apps.AppID) ([]*model.Session, error) + Delete(r *incoming.Request, appID apps.AppID, userID string) error DeleteAllForApp(*incoming.Request, apps.AppID) error DeleteAllForUser(_ *incoming.Request, userID string) error } -type sessionStore struct { - *Service -} - -var _ SessionStore = (*sessionStore)(nil) - func sessionKey(appID apps.AppID, userID string) string { return appKey(appID) + "_" + userID } func appKey(appID apps.AppID) string { - return KVTokenPrefix + "_" + string(appID) + return TokenPrefix + "_" + string(appID) } func parseSessionKey(key string) (apps.AppID, string, error) { //nolint:golint,unparam @@ -41,20 +37,20 @@ func parseSessionKey(key string) (apps.AppID, string, error) { //nolint:golint,u return "", "", errors.New("invalid key pattern") } - if s[0] != KVTokenPrefix { + if s[0] != TokenPrefix { return "", "", errors.New("invalid key prefix") } return apps.AppID(s[1]), s[2], nil } -func (s sessionStore) Get(appID apps.AppID, userID string) (*model.Session, error) { - return s.get(sessionKey(appID, userID)) +func (s SessionStore) Get(r *incoming.Request, appID apps.AppID, userID string) (*model.Session, error) { + return s.get(r, sessionKey(appID, userID)) } -func (s sessionStore) get(key string) (*model.Session, error) { +func (s SessionStore) get(r *incoming.Request, key string) (*model.Session, error) { var session model.Session - err := s.conf.API().Mattermost.KV.Get(key, &session) + err := r.API.Mattermost.KV.Get(key, &session) if err != nil { return nil, err } @@ -66,8 +62,8 @@ func (s sessionStore) get(key string) (*model.Session, error) { return &session, nil } -func (s sessionStore) Save(appID apps.AppID, userID string, session *model.Session) error { - _, err := s.conf.API().Mattermost.KV.Set(sessionKey(appID, userID), session) +func (s SessionStore) Save(r *incoming.Request, appID apps.AppID, userID string, session *model.Session) error { + _, err := r.API.Mattermost.KV.Set(sessionKey(appID, userID), session) if err != nil { return err } @@ -75,11 +71,11 @@ func (s sessionStore) Save(appID apps.AppID, userID string, session *model.Sessi return nil } -func (s sessionStore) listKeysForApp(appID apps.AppID) ([]string, error) { +func (s SessionStore) listKeysForApp(r *incoming.Request, appID apps.AppID) ([]string, error) { ret := make([]string, 0) for i := 0; ; i++ { - keys, err := s.conf.API().Mattermost.KV.ListKeys(i, ListKeysPerPage) + keys, err := r.API.Mattermost.KV.ListKeys(i, ListKeysPerPage) if err != nil { return nil, errors.Wrapf(err, "failed to list keys - page, %d", i) } @@ -96,11 +92,11 @@ func (s sessionStore) listKeysForApp(appID apps.AppID) ([]string, error) { return ret, nil } -func (s sessionStore) listKeysForUser(userID string) ([]string, error) { +func (s SessionStore) listKeysForUser(r *incoming.Request, userID string) ([]string, error) { ret := make([]string, 0) for i := 0; ; i++ { - keys, err := s.conf.API().Mattermost.KV.ListKeys(i, ListKeysPerPage) + keys, err := r.API.Mattermost.KV.ListKeys(i, ListKeysPerPage) if err != nil { return nil, errors.Wrapf(err, "failed to list keys - page, %d", i) } @@ -124,8 +120,8 @@ func (s sessionStore) listKeysForUser(userID string) ([]string, error) { return ret, nil } -func (s sessionStore) ListForApp(appID apps.AppID) ([]*model.Session, error) { - keys, err := s.listKeysForApp(appID) +func (s SessionStore) ListForApp(r *incoming.Request, appID apps.AppID) ([]*model.Session, error) { + keys, err := s.listKeysForApp(r, appID) if err != nil { return nil, err } @@ -133,7 +129,7 @@ func (s sessionStore) ListForApp(appID apps.AppID) ([]*model.Session, error) { ret := make([]*model.Session, 0) for _, key := range keys { - session, err := s.get(key) + session, err := s.get(r, key) if err != nil { return nil, errors.Wrapf(err, "failed get key, %s", key) } @@ -144,11 +140,11 @@ func (s sessionStore) ListForApp(appID apps.AppID) ([]*model.Session, error) { return ret, nil } -func (s sessionStore) ListForUser(r *incoming.Request, userID string) ([]*model.Session, error) { +func (s SessionStore) ListForUser(r *incoming.Request, userID string) ([]*model.Session, error) { ret := make([]*model.Session, 0) for i := 0; ; i++ { - keys, err := s.conf.API().Mattermost.KV.ListKeys(i, ListKeysPerPage) + keys, err := r.API.Mattermost.KV.ListKeys(i, ListKeysPerPage) if err != nil { return nil, errors.Wrapf(err, "failed to list keys - page, %d", i) } @@ -166,7 +162,7 @@ func (s sessionStore) ListForUser(r *incoming.Request, userID string) ([]*model. continue } - session, err := s.get(key) + session, err := s.get(r, key) if err != nil { r.Log.WithError(err).Debugf("failed get session for key, %s", key) continue @@ -179,18 +175,18 @@ func (s sessionStore) ListForUser(r *incoming.Request, userID string) ([]*model. return ret, nil } -func (s sessionStore) Delete(appID apps.AppID, userID string) error { - return s.conf.API().Mattermost.KV.Delete(sessionKey(appID, userID)) +func (s SessionStore) Delete(r *incoming.Request, appID apps.AppID, userID string) error { + return r.API.Mattermost.KV.Delete(sessionKey(appID, userID)) } -func (s sessionStore) DeleteAllForApp(r *incoming.Request, appID apps.AppID) error { - keys, err := s.listKeysForApp(appID) +func (s SessionStore) DeleteAllForApp(r *incoming.Request, appID apps.AppID) error { + keys, err := s.listKeysForApp(r, appID) if err != nil { return err } for _, key := range keys { - err := s.conf.API().Mattermost.KV.Delete(key) + err := r.API.Mattermost.KV.Delete(key) if err != nil { r.Log.WithError(err).Debugf("failed delete session for key: %s, appID: %s", key, appID) } @@ -199,14 +195,14 @@ func (s sessionStore) DeleteAllForApp(r *incoming.Request, appID apps.AppID) err return nil } -func (s sessionStore) DeleteAllForUser(r *incoming.Request, userID string) error { - keys, err := s.listKeysForUser(userID) +func (s SessionStore) DeleteAllForUser(r *incoming.Request, userID string) error { + keys, err := s.listKeysForUser(r, userID) if err != nil { return err } for _, key := range keys { - err := s.conf.API().Mattermost.KV.Delete(key) + err := r.API.Mattermost.KV.Delete(key) if err != nil { r.Log.WithError(err).Debugf("failed delete session for key: %s, userID: %s", key, userID) } diff --git a/server/store/subscriptions.go b/server/store/subscriptions.go index ae2adf712..6d2488596 100644 --- a/server/store/subscriptions.go +++ b/server/store/subscriptions.go @@ -4,141 +4,76 @@ package store import ( - "strings" + "encoding/json" + "fmt" "github.com/pkg/errors" "github.com/mattermost/mattermost-plugin-apps/apps" + "github.com/mattermost/mattermost-plugin-apps/server/incoming" "github.com/mattermost/mattermost-plugin-apps/utils" ) -// SubscriptionStore stores the complete (for all apps) list of subscriptions -// for each "scope", everything in apps.Subscription, but the Call - the -// subject, and the optional team/channel IDs. -type SubscriptionStore interface { - Get(apps.Event) ([]Subscription, error) - List() ([]StoredSubscriptions, error) - Save(apps.Event, []Subscription) error -} - type Subscription struct { - Call apps.Call + Call apps.Call `json:"call"` AppID apps.AppID `json:"app_id"` OwnerUserID string `json:"user_id"` } -type StoredSubscriptions struct { - Event apps.Event - Subscriptions []Subscription -} +type Subscriptions []Subscription -type subscriptionStore struct { - *Service +func (s Subscriptions) Clone() *Subscriptions { + out := make(Subscriptions, len(s)) + copy(out, s) + return &out } -var _ SubscriptionStore = (*subscriptionStore)(nil) - -func subsKey(e apps.Event) (string, error) { - idSuffix := "" - switch e.Subject { - case apps.SubjectUserCreated, - apps.SubjectBotJoinedTeam, apps.SubjectBotLeftTeam, - apps.SubjectBotJoinedChannel, apps.SubjectBotLeftChannel: - if e.TeamID != "" || e.ChannelID != "" { - return "", errors.Errorf("can't make a key for a subscription, expected team and channel IDs empty for subject %s", e.Subject) - } - - case apps.SubjectUserJoinedChannel, apps.SubjectUserLeftChannel /* , apps.SubjectPostCreated */ : - if e.TeamID != "" { - return "", errors.Errorf("can't make a key for a subscription, expected team ID empty for subject %s", e.Subject) - } - if e.ChannelID != "" { - idSuffix = "." + e.ChannelID - } - - case apps.SubjectUserJoinedTeam, apps.SubjectUserLeftTeam: - if e.ChannelID != "" { - return "", errors.Errorf("can't make a key for a subscription, expected channel ID empty for subject %s", e.Subject) - } - if e.TeamID != "" { - idSuffix = "." + e.TeamID - } - - case apps.SubjectChannelCreated: - if e.ChannelID != "" { - return "", errors.Errorf("can't make a key for a subscription, expected channel ID empty for subject %s", e.Subject) - } - if e.TeamID == "" { - return "", errors.Errorf("can't make a key for a subscription, expected a team ID for subject %s", e.Subject) - } - idSuffix = "." + e.TeamID - - default: - return "", errors.Errorf("Unknown subject %s", e.Subject) - } - - return KVSubPrefix + string(e.Subject) + idSuffix, nil +type SubscriptionStore struct { + CachedStore[Subscriptions] } -func (s subscriptionStore) Get(e apps.Event) ([]Subscription, error) { - key, err := subsKey(e) +func (s *Service) makeSubscriptionStore(log utils.Logger) (*SubscriptionStore, error) { + cached, err := MakeCachedStore[Subscriptions](SubscriptionStoreName, s.cluster, log) if err != nil { return nil, err } + return &SubscriptionStore{ + CachedStore: cached, + }, nil +} - stored := &StoredSubscriptions{} - err = s.conf.API().Mattermost.KV.Get(key, &stored) - if err != nil { - return nil, err +func (s *SubscriptionStore) Get(_ *incoming.Request, e apps.Event) (Subscriptions, error) { + key := utils.ToJSON(e) + if key == "{}" { + return nil, errors.New("failed to get subscriptions: invalid empty event") } - if stored == nil { - return nil, utils.ErrNotFound + subs := s.CachedStore.Get(key) + if subs == nil { + return nil, errors.Wrapf(utils.ErrNotFound, "failed to get subscriptions for event %s", e.String()) } - return stored.Subscriptions, nil + return *subs, nil } -func (s subscriptionStore) List() ([]StoredSubscriptions, error) { - all := []StoredSubscriptions{} - for i := 0; ; i++ { - keys, err := s.conf.API().Mattermost.KV.ListKeys(i, ListKeysPerPage) - if err != nil { - return nil, errors.Wrapf(err, "failed to list keys - page, %d", i) - } - if len(keys) == 0 { - break - } - - for _, key := range keys { - if !strings.HasPrefix(key, KVSubPrefix) { - continue - } - forKey := StoredSubscriptions{} - err := s.conf.API().Mattermost.KV.Get(key, &forKey) - if err != nil { - return nil, err - } - if forKey.Event.Subject == "" { - continue - } - all = append(all, forKey) +func (s *SubscriptionStore) ListSubscribedEvents(_ *incoming.Request) ([]apps.Event, error) { + var events []apps.Event + for eventJSON := range s.Index() { + var e apps.Event + if err := json.Unmarshal([]byte(eventJSON), &e); err != nil { + return nil, err } + events = append(events, e) } - return all, nil + return events, nil } -func (s subscriptionStore) Save(e apps.Event, subs []Subscription) error { - key, err := subsKey(e) - if err != nil { - return err - } - - if len(subs) == 0 { - return s.conf.API().Mattermost.KV.Delete(key) +func (s *SubscriptionStore) Put(r *incoming.Request, e apps.Event, subs *Subscriptions) error { + key := utils.ToJSON(e) + if key == "{}" { + return errors.New("failed to save subscriptions: invalid empty event") } + return s.CachedStore.Put(r, key, subs) +} - _, err = s.conf.API().Mattermost.KV.Set(key, StoredSubscriptions{ - Event: e, - Subscriptions: subs, - }) - return err +func (s Subscription) String() string { + return fmt.Sprintf("%s/%s/%s", s.AppID, s.OwnerUserID, s.Call.Path) } diff --git a/server/store/subscriptions_test.go b/server/store/subscriptions_test.go deleted file mode 100644 index 5bbc006c4..000000000 --- a/server/store/subscriptions_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package store - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/mattermost/mattermost-plugin-apps/apps" -) - -func Test_subsKey(t *testing.T) { - type testcase struct { - e apps.Event - expected string - } - - tcs := func(subject apps.Subject, expectedNone string, expectedChannelID string, expectedTeamID string, expectedBoth string) []testcase { - return []testcase{ - { - e: apps.Event{Subject: subject}, - expected: expectedNone, - }, - { - e: apps.Event{Subject: subject, ChannelID: "channelID"}, - expected: expectedChannelID, - }, - { - e: apps.Event{Subject: subject, TeamID: "teamID"}, - expected: expectedTeamID, - }, - { - e: apps.Event{Subject: subject, ChannelID: "channelID", TeamID: "teamID"}, - expected: expectedBoth, - }, - } - } - - tests := []testcase{} - tests = append(tests, tcs(apps.SubjectChannelCreated, - "can't make a key for a subscription, expected a team ID for subject channel_created", - "can't make a key for a subscription, expected channel ID empty for subject channel_created", - "sub.channel_created.teamID", - "can't make a key for a subscription, expected channel ID empty for subject channel_created")...) - - tests = append(tests, tcs(apps.SubjectUserCreated, - "sub.user_created", - "can't make a key for a subscription, expected team and channel IDs empty for subject user_created", - "can't make a key for a subscription, expected team and channel IDs empty for subject user_created", - "can't make a key for a subscription, expected team and channel IDs empty for subject user_created")...) - - tests = append(tests, tcs(apps.SubjectUserJoinedChannel, - "sub.user_joined_channel", - "sub.user_joined_channel.channelID", - "can't make a key for a subscription, expected team ID empty for subject user_joined_channel", - "can't make a key for a subscription, expected team ID empty for subject user_joined_channel")...) - - tests = append(tests, tcs(apps.SubjectUserLeftChannel, - "sub.user_left_channel", - "sub.user_left_channel.channelID", - "can't make a key for a subscription, expected team ID empty for subject user_left_channel", - "can't make a key for a subscription, expected team ID empty for subject user_left_channel")...) - - tests = append(tests, tcs(apps.SubjectUserJoinedTeam, - "sub.user_joined_team", - "can't make a key for a subscription, expected channel ID empty for subject user_joined_team", - "sub.user_joined_team.teamID", - "can't make a key for a subscription, expected channel ID empty for subject user_joined_team")...) - - tests = append(tests, tcs(apps.SubjectUserLeftTeam, - "sub.user_left_team", - "can't make a key for a subscription, expected channel ID empty for subject user_left_team", - "sub.user_left_team.teamID", - "can't make a key for a subscription, expected channel ID empty for subject user_left_team")...) - - tests = append(tests, tcs(apps.SubjectBotJoinedChannel, - "sub.bot_joined_channel", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_joined_channel", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_joined_channel", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_joined_channel")...) - - tests = append(tests, tcs(apps.SubjectBotLeftChannel, - "sub.bot_left_channel", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_left_channel", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_left_channel", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_left_channel")...) - - tests = append(tests, tcs(apps.SubjectBotJoinedTeam, - "sub.bot_joined_team", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_joined_team", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_joined_team", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_joined_team")...) - - tests = append(tests, tcs(apps.SubjectBotLeftTeam, - "sub.bot_left_team", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_left_team", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_left_team", - "can't make a key for a subscription, expected team and channel IDs empty for subject bot_left_team")...) - - for _, tc := range tests { - t.Run(tc.e.String(), func(t *testing.T) { - got, err := subsKey(tc.e) - if err != nil { - got = err.Error() - } - require.Equal(t, tc.expected, got) - }) - } -} diff --git a/test/restapitest/bindings.go b/test/restapitest/bindings.go index 66d9e94b5..6cfeb00f1 100644 --- a/test/restapitest/bindings.go +++ b/test/restapitest/bindings.go @@ -306,7 +306,6 @@ func testBindings(th *Helper) { }) th.Run("multiple apps have commands", func(th *Helper) { - th.Skip("https://mattermost.atlassian.net/browse/MM-48405") app1ID := apps.AppID("bind1") app1 := newBindingsApp(th, app1ID, nil, []apps.Binding{ diff --git a/test/restapitest/kv.go b/test/restapitest/kv.go index 4e3ad4375..892e2ad37 100644 --- a/test/restapitest/kv.go +++ b/test/restapitest/kv.go @@ -15,6 +15,8 @@ import ( "github.com/mattermost/mattermost-plugin-apps/apps" "github.com/mattermost/mattermost-plugin-apps/apps/appclient" "github.com/mattermost/mattermost-plugin-apps/apps/goapp" + "github.com/mattermost/mattermost-plugin-apps/server/builtin" + "github.com/mattermost/mattermost-plugin-apps/server/store" "github.com/mattermost/mattermost-plugin-apps/utils" ) @@ -84,7 +86,7 @@ func newKVApp(t testing.TB) *goapp.App { } //nolint:golint,unparam -func kvCall(th *Helper, path string, asBot bool, prefix, key string, value interface{}) apps.CallResponse { +func kvCall(th *Helper, path string, asBot bool, prefix, key string, value interface{}) *apps.CallResponse { creq := apps.CallRequest{ Call: *apps.NewCall(path), Values: model.StringInterface{ @@ -106,7 +108,7 @@ func kvCall(th *Helper, path string, asBot bool, prefix, key string, value inter if value != nil { creq.Values["value"] = value } - return *th.HappyCall(kvID, creq) + return th.HappyCall(kvID, creq) } func testKV(th *Helper) { @@ -240,4 +242,48 @@ func testKV(th *Helper) { }) // TODO: Add a test for namespacing 2 separate users + + th.Run("debug info", func(th *Helper) { + cresp := kvCall(th, "/set", false, "p1", "testkey1", model.StringInterface{"n": "v"}) + require.Equal(th, "true", cresp.Text) + cresp = kvCall(th, "/set", false, "p2", "testkey2", model.StringInterface{"n": "v"}) + require.Equal(th, "true", cresp.Text) + + th.Cleanup(func() { + _ = kvCall(th, "/delete", false, "p1", "testkey1", nil) + _ = kvCall(th, "/delete", false, "p2", "testkey2", nil) + th.Logf("deleted test KV keys") + }) + + infoRequest := apps.CallRequest{ + Call: *apps.NewCall(builtin.PathDebugKVInfo).WithExpand(apps.Expand{ActingUser: apps.ExpandSummary}), + } + cresp = th.HappyAdminCall(builtin.AppID, infoRequest) + info := store.KVDebugInfo{} + utils.Remarshal(&info, cresp.Data) + + require.EqualValues(th, + store.KVDebugInfo{ + Apps: map[apps.AppID]*store.KVDebugAppInfo{ + "kvtest": { + AppKVCount: 2, + AppKVCountByNamespace: map[string]int{"p1": 1, "p2": 1}, + AppKVCountByUserID: map[string]int{th.ServerTestHelper.BasicUser.Id: 2}, + TokenCount: 2, + UserCount: 0, + }, + }, + AppsTotal: 4, + CachedStoreTotal: 4, + CachedStoreCountByName: map[string]int{ + "apps": 1, + "manifests": 1, + }, + Debug: 0, + OAuth2StateCount: 0, + Other: 0, + Total: 8, + }, + info) + }) } diff --git a/test/restapitest/oauth2.go b/test/restapitest/oauth2.go index 40ca842c9..7808a34ed 100644 --- a/test/restapitest/oauth2.go +++ b/test/restapitest/oauth2.go @@ -221,7 +221,6 @@ func testOAuth2(th *Helper) { }) th.Run("User and bot calls can expand OAuth2App", func(th *Helper) { - th.Skip("https://mattermost.atlassian.net/browse/MM-48448") th.Cleanup(func() { cleanupOAuth2App(th)() cleanupOAuth2User(th)() diff --git a/test/restapitest/subscribe.go b/test/restapitest/subscribe.go index adac947f8..f54f94e31 100644 --- a/test/restapitest/subscribe.go +++ b/test/restapitest/subscribe.go @@ -5,6 +5,7 @@ package restapitest import ( "encoding/json" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -21,10 +22,10 @@ import ( const subID = apps.AppID("subtest") -func newSubscribeApp(t testing.TB) *goapp.App { +func newSubscribeApp(t testing.TB, appID apps.AppID) *goapp.App { app := goapp.MakeAppOrPanic( apps.Manifest{ - AppID: subID, + AppID: appID, Version: "v1.2.0", DisplayName: "tests Subscription API", HomepageURL: "https://github.com/mattermost/mattermost-plugin-apps/test/restapitest", @@ -84,7 +85,11 @@ func newSubscribeApp(t testing.TB) *goapp.App { } func assertNumSubs(th *Helper, callf Caller, n int) { - cresp := callf(subID, subCallRequest("/list", false, "", "", "")) + assertNumSubsForID(th, callf, n, subID) +} + +func assertNumSubsForID(th *Helper, callf Caller, n int, appID apps.AppID) { + cresp := callf(appID, subCallRequest("/list", false, "", "", "")) subs := []apps.Subscription{} err := json.Unmarshal([]byte(cresp.Text), &subs) require.NoError(th, err) @@ -111,7 +116,7 @@ func subCallRequest(path string, asBot bool, subject apps.Subject, teamID, chann } func testSubscriptions(th *Helper) { - th.InstallAppWithCleanup(newSubscribeApp(th.T)) + th.InstallAppWithCleanup(newSubscribeApp(th.T, subID)) th.Run("Unauthenticated requests are rejected", func(th *Helper) { assert := assert.New(th) @@ -149,13 +154,48 @@ func testSubscriptions(th *Helper) { cresp = th.HappyCall(subID, subCallRequest("/unsubscribe", false, apps.SubjectUserCreated, "", "")) require.Equal(th, `unsubscribed`, cresp.Text) assertNumSubs(th, th.HappyCall, 2) + }) + + th.Run("unsubscribe fails not subscribed", func(th *Helper) { + otherID := subID + "-other" + th.InstallAppWithCleanup(newSubscribeApp(th.T, otherID)) + + assertNumSubsForID(th, th.HappyCall, 0, subID) + assertNumSubsForID(th, th.HappyCall, 0, otherID) - // Unsubscribe from a non-existing subscription. - badResponse, _, err := th.Call(subID, subCallRequest("/unsubscribe", false, apps.SubjectChannelCreated, "does-not-exist", "")) + cresp := th.HappyCall(subID, subCallRequest("/subscribe", false, apps.SubjectChannelCreated, th.ServerTestHelper.BasicTeam.Id, "")) + require.Equal(th, `subscribed`, cresp.Text) + cresp = th.HappyCall(otherID, subCallRequest("/subscribe", false, apps.SubjectChannelCreated, th.ServerTestHelper.BasicTeam.Id, "")) + require.Equal(th, `subscribed`, cresp.Text) + assertNumSubsForID(th, th.HappyCall, 1, subID) + assertNumSubsForID(th, th.HappyCall, 1, otherID) + th.Cleanup(func() { + _, _, _ = th.Call(subID, subCallRequest("/unsubscribe", false, apps.SubjectChannelCreated, th.ServerTestHelper.BasicTeam.Id, "")) + _, _, _ = th.Call(otherID, subCallRequest("/unsubscribe", false, apps.SubjectChannelCreated, th.ServerTestHelper.BasicTeam.Id, "")) + assertNumSubsForID(th, th.HappyCall, 0, subID) + assertNumSubsForID(th, th.HappyCall, 0, otherID) + }) + + cresp = th.HappyCall(subID, subCallRequest("/unsubscribe", false, apps.SubjectChannelCreated, th.ServerTestHelper.BasicTeam.Id, "")) + require.Equal(th, `unsubscribed`, cresp.Text) + assertNumSubsForID(th, th.HappyCall, 0, subID) + assertNumSubsForID(th, th.HappyCall, 1, otherID) + + // Unsubscribe again should fail + badResponse, _, err := th.Call(subID, subCallRequest("/unsubscribe", false, apps.SubjectChannelCreated, th.ServerTestHelper.BasicTeam.Id, "")) require.NoError(th, err) require.Equal(th, apps.CallResponseTypeError, badResponse.Type) - require.Equal(th, "You are not subscribed to this notification: not found", badResponse.Text) - assertNumSubs(th, th.HappyCall, 2) + require.Equal(th, fmt.Sprintf("failed to get subscriptions for event subject: channel_created, team_id: %s: not found", th.ServerTestHelper.BasicTeam.Id), badResponse.Text) + assertNumSubsForID(th, th.HappyCall, 0, subID) + assertNumSubsForID(th, th.HappyCall, 1, otherID) + + // Unsubscribe to a non-existing subscription should fail + badResponse, _, err = th.Call(subID, subCallRequest("/unsubscribe", false, apps.SubjectChannelCreated, "does-not-exist", "")) + require.NoError(th, err) + require.Equal(th, apps.CallResponseTypeError, badResponse.Type) + require.Equal(th, "failed to get subscriptions for event subject: channel_created, team_id: does-not-exist: not found", badResponse.Text) + assertNumSubsForID(th, th.HappyCall, 0, subID) + assertNumSubsForID(th, th.HappyCall, 1, otherID) }) th.Run("subscribe as bot list as user", func(th *Helper) { diff --git a/test/restapitest/uninstall.go b/test/restapitest/uninstall.go index 24c165d1d..4b026323a 100644 --- a/test/restapitest/uninstall.go +++ b/test/restapitest/uninstall.go @@ -36,50 +36,49 @@ func newUninstallApp(th *Helper) *goapp.App { ) app.HandleCall("/install", func(creq goapp.CallRequest) apps.CallResponse { - th.Run("create test data", func(th *Helper) { - require.NotNil(th, creq.Context.ActingUser, "must be called as the acting user") - require.NotEmpty(th, creq.Context.ActingUser.Id) - require.NotEmpty(th, creq.Context.ActingUserAccessToken) - require.NotEqual(th, creq.Context.BotUserID, creq.Context.ActingUser.Id, "must be called as the user running the InstallApp API, not as the bot") - - // Create KV data - testv := map[string]interface{}{"field": "test-value"} - setKV := func(client *appclient.Client, prefix, key string) { - changed, err := client.KVSet(prefix, key, testv) - require.True(th, changed) - require.NoError(th, err) - } - setKV(creq.AsBot(), "p1", "id1") - setKV(creq.AsBot(), "", "id2") - setKV(creq.AsActingUser(), "p1", "id1") - setKV(creq.AsActingUser(), "p2", "id2") - - // Create subscriptions. - subscribe := func(client *appclient.Client, event apps.Event) { - err := client.Subscribe(&apps.Subscription{ - Event: event, - Call: *apps.NewCall("/echo"), - }) - require.NoError(th, err) - } - subscribe(creq.AsBot(), apps.Event{Subject: apps.SubjectUserJoinedChannel}) - subscribe(creq.AsBot(), apps.Event{Subject: apps.SubjectUserJoinedTeam}) - subscribe(creq.AsActingUser(), apps.Event{Subject: apps.SubjectUserJoinedChannel}) - subscribe(creq.AsActingUser(), apps.Event{Subject: apps.SubjectChannelCreated, TeamID: th.ServerTestHelper.BasicTeam.Id}) - subscribe(creq.AsActingUser(), apps.Event{Subject: apps.SubjectUserJoinedChannel, ChannelID: th.ServerTestHelper.BasicChannel.Id}) - - // Create OAuth2 data - err := creq.AsActingUser().StoreOAuth2App(apps.OAuth2App{ - ClientID: "testing", - ClientSecret: "testingSecret", + require.NotNil(th, creq.Context.ActingUser, "must be called as the acting user") + require.NotEmpty(th, creq.Context.ActingUser.Id) + require.NotEmpty(th, creq.Context.ActingUserAccessToken) + require.NotEqual(th, creq.Context.BotUserID, creq.Context.ActingUser.Id, "must be called as the user running the InstallApp API, not as the bot") + + // Create KV data + testv := map[string]any{"field": "test-value"} + setKV := func(client *appclient.Client, prefix, key string) { + changed, err := client.KVSet(prefix, key, testv) + require.True(th, changed) + require.NoError(th, err) + } + setKV(creq.AsBot(), "p1", "id1") + setKV(creq.AsBot(), "", "id2") + setKV(creq.AsActingUser(), "p1", "id1") + setKV(creq.AsActingUser(), "p2", "id2") + + // Create subscriptions. + subscribe := func(client *appclient.Client, event apps.Event) { + err := client.Subscribe(&apps.Subscription{ + Event: event, + Call: *apps.NewCall("/echo"), }) require.NoError(th, err) - setUser := func(client *appclient.Client) { - err := client.StoreOAuth2User("testing") - require.NoError(th, err) - } - setUser(creq.AsActingUser()) + } + subscribe(creq.AsBot(), apps.Event{Subject: apps.SubjectUserJoinedChannel}) + subscribe(creq.AsBot(), apps.Event{Subject: apps.SubjectUserJoinedTeam}) + subscribe(creq.AsActingUser(), apps.Event{Subject: apps.SubjectUserJoinedChannel}) + subscribe(creq.AsActingUser(), apps.Event{Subject: apps.SubjectChannelCreated, TeamID: th.ServerTestHelper.BasicTeam.Id}) + subscribe(creq.AsActingUser(), apps.Event{Subject: apps.SubjectUserJoinedChannel, ChannelID: th.ServerTestHelper.BasicChannel.Id}) + + // Create OAuth2 data + err := creq.AsActingUser().StoreOAuth2App(apps.OAuth2App{ + ClientID: "testing", + ClientSecret: "testingSecret", }) + require.NoError(th, err) + + setUser := func(client *appclient.Client) { + err := client.StoreOAuth2User("testing") + require.NoError(th, err) + } + setUser(creq.AsActingUser()) return apps.NewTextResponse("installed") }) @@ -87,17 +86,15 @@ func newUninstallApp(th *Helper) *goapp.App { } func testUninstall(th *Helper) { - info := apps.CallRequest{ + infoRequest := apps.CallRequest{ Call: *apps.NewCall(builtin.PathDebugKVInfo).WithExpand(apps.Expand{ActingUser: apps.ExpandSummary}), } pollute := func(n int) { - th.Run(fmt.Sprintf("add %v garbage KV entries", n), func(th *Helper) { - cresp := th.HappyAdminCall(builtin.AppID, apps.CallRequest{ - Call: *apps.NewCall(builtin.PathDebugStorePollute).WithExpand(apps.Expand{ActingUser: apps.ExpandSummary}), - Values: map[string]interface{}{"count": fmt.Sprintf("%v", n)}, - }) - require.Equal(th, apps.CallResponseTypeOK, cresp.Type) + cresp := th.HappyAdminCall(builtin.AppID, apps.CallRequest{ + Call: *apps.NewCall(builtin.PathDebugStorePollute).WithExpand(apps.Expand{ActingUser: apps.ExpandSummary}), + Values: map[string]any{"count": fmt.Sprintf("%v", n)}, }) + require.Equal(th, apps.CallResponseTypeOK, cresp.Type) } pollute(599) @@ -105,44 +102,51 @@ func testUninstall(th *Helper) { pollute(1401) th.Run("check test app data", func(th *Helper) { - cresp := th.HappyAdminCall(builtin.AppID, info) + cresp := th.HappyAdminCall(builtin.AppID, infoRequest) require.Equal(th, apps.CallResponseTypeOK, cresp.Type) info := store.KVDebugInfo{} utils.Remarshal(&info, cresp.Data) require.Len(th, info.Apps, 1) - info.Apps[uninstallID].AppKVCountByUserID = nil require.EqualValues(th, store.KVDebugInfo{ - Total: 2013, - AppsTotal: 7, - InstalledAppCount: 1, - ManifestCount: 1, - OAuth2StateCount: 0, - Other: 0, // debug clean before the test clears out the special bot key; was: 1 - SubscriptionCount: 4, - Debug: 2000, Apps: map[apps.AppID]*store.KVDebugAppInfo{ - "uninstalltest": { + th.LastInstalledApp.Manifest.AppID: { AppKVCount: 4, AppKVCountByNamespace: map[string]int{"": 1, "p1": 2, "p2": 1}, + AppKVCountByUserID: map[string]int{th.LastInstalledApp.BotUserID: 2, th.ServerTestHelper.SystemAdminUser.Id: 2}, TokenCount: 2, UserCount: 1, }, }, + AppsTotal: 7, + CachedStoreTotal: 9, + CachedStoreCountByName: map[string]int{ + "apps": 1, + "manifests": 1, + "subscriptions": 4, + }, + Debug: 2000, + Total: 2016, }, info) }) th.UninstallApp(uninstallID) + th.Run("uninstall clears KV data", func(th *Helper) { - cresp := th.HappyAdminCall(builtin.AppID, info) + cresp := th.HappyAdminCall(builtin.AppID, infoRequest) require.Equal(th, apps.CallResponseTypeOK, cresp.Type) info := store.KVDebugInfo{} utils.Remarshal(&info, cresp.Data) require.EqualValues(th, store.KVDebugInfo{ - Total: 2001, - ManifestCount: 1, - Other: 0, // debug clean before the test clears out the special bot key; was: 1 - Debug: 2000, - Apps: map[apps.AppID]*store.KVDebugAppInfo{}, + Apps: map[apps.AppID]*store.KVDebugAppInfo{}, + AppsTotal: 0, + CachedStoreTotal: 4, + CachedStoreCountByName: map[string]int{ + "manifests": 1, + }, + Debug: 2000, + OAuth2StateCount: 0, + Other: 0, + Total: 2004, }, info) }) diff --git a/utils/logger.go b/utils/logger.go index 75930e53b..c3a39c4cc 100644 --- a/utils/logger.go +++ b/utils/logger.go @@ -5,9 +5,12 @@ package utils import ( "fmt" + "hash/fnv" + "os" "sort" "strings" + "github.com/goombaio/namegenerator" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -160,3 +163,11 @@ func LogDigest(i interface{}) string { return fmt.Sprintf("%v", i) } + +func HostNickname() string { + hostname, _ := os.Hostname() + + h := fnv.New64a() + h.Write([]byte(hostname)) + return namegenerator.NewNameGenerator(int64(h.Sum64())).Generate() +} diff --git a/utils/plugin_logger.go b/utils/plugin_logger.go index 27261e7a2..e25d2b1d2 100644 --- a/utils/plugin_logger.go +++ b/utils/plugin_logger.go @@ -46,7 +46,7 @@ func NewPluginLogger(mmapi *pluginapi.Client, confGetter LogConfigGetter) Logger logger: &mmapi.Log, LevelEnabler: zapcore.DebugLevel, confGetter: confGetter, - }, options).Sugar(), + }, options).Sugar().Named(HostNickname()), } } @@ -118,7 +118,7 @@ func (p *plugin) Write(e zapcore.Entry, fields []zapcore.Field) error { return nil } - message := fmt.Sprintf("%s %s (%s): %s\n", e.Time.Format(time.StampMilli), e.Level.CapitalString(), caller, e.Message) + message := fmt.Sprintf("%s: %s **%s** (%s): %s\n", e.LoggerName, e.Time.Format(time.StampMilli), e.Level.CapitalString(), caller, e.Message) if logconf.IncludeJSON { ccJSON := map[string]any{}