cmd/gateway: use a separate repository

Change-Id: Idbb0b2b6cf0e60c6d5d91218c24524d72285cf26
This commit is contained in:
Egon Elbre 2020-02-21 18:28:20 +02:00
parent 5011e78311
commit e30f7b35b6
16 changed files with 654 additions and 2632 deletions

View File

@ -82,9 +82,9 @@ install-sim: ## install storj-sim
storj.io/storj/cmd/storj-sim \
storj.io/storj/cmd/versioncontrol \
storj.io/storj/cmd/uplink \
storj.io/storj/cmd/gateway \
storj.io/storj/cmd/identity \
storj.io/storj/cmd/certificates
cd cmd/gateway && go install -race -v storj.io/storj/cmd/gateway
##@ Test

57
cmd/gateway/go.mod Normal file
View File

@ -0,0 +1,57 @@
module storj.io/storj/cmd/gateway
go 1.13
// force specific versions for minio
require github.com/garyburd/redigo v1.0.1-0.20170216214944-0d253a66e6e1 // indirect
replace storj.io/storj => ../../
require storj.io/gateway v0.0.0-20200221161528-36f00ab51fa7
exclude gopkg.in/olivere/elastic.v5 v5.0.72 // buggy import, see https://github.com/olivere/elastic/pull/869
replace google.golang.org/grpc => github.com/storj/grpc-go v1.23.1-0.20190918084400-1c4561bf5127
require (
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
github.com/cheggaaa/pb v1.0.5-0.20160713104425-73ae1d68fe0b // indirect
github.com/djherbis/atime v1.0.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/eclipse/paho.mqtt.golang v1.1.1 // indirect
github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect
github.com/fatih/structs v1.0.0 // indirect
github.com/go-ini/ini v1.52.0 // indirect
github.com/gorilla/handlers v1.4.0 // indirect
github.com/gorilla/rpc v1.1.0 // indirect
github.com/hashicorp/go-immutable-radix v1.0.0 // indirect
github.com/hashicorp/go-msgpack v0.5.3 // indirect
github.com/hashicorp/raft v1.0.0 // indirect
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf // indirect
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e // indirect
github.com/klauspost/reedsolomon v0.0.0-20180704173009-925cb01d6510 // indirect
github.com/minio/dsync v0.0.0-20180124070302-439a0961af70 // indirect
github.com/minio/highwayhash v0.0.0-20180501080913-85fc8a2dacad // indirect
github.com/minio/lsync v0.0.0-20180328070428-f332c3883f63 // indirect
github.com/minio/mc v0.0.0-20180926130011-a215fbb71884 // indirect
github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0 // indirect
github.com/nats-io/gnatsd v1.3.0 // indirect
github.com/nats-io/go-nats v1.6.0 // indirect
github.com/nats-io/go-nats-streaming v0.4.2 // indirect
github.com/nats-io/nats v1.6.0 // indirect
github.com/nats-io/nats-streaming-server v0.12.2 // indirect
github.com/nats-io/nuid v1.0.0 // indirect
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c // indirect
github.com/pkg/profile v1.2.1 // indirect
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e // indirect
github.com/rs/cors v1.5.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/streadway/amqp v0.0.0-20180806233856-70e15c650864 // indirect
github.com/tidwall/gjson v1.1.3 // indirect
github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1 // indirect
google.golang.org/appengine v1.6.0 // indirect
gopkg.in/Shopify/sarama.v1 v1.18.0 // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.25 // indirect
gopkg.in/ini.v1 v1.52.0 // indirect
gopkg.in/olivere/elastic.v5 v5.0.76 // indirect
)

573
cmd/gateway/go.sum Normal file
View File

@ -0,0 +1,573 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/go-lua v0.0.0-20181106184032-48449c60c0a9/go.mod h1:lvS2IGWEGk+KQkRrCXuWlcsHO5BitT0HyhnP51rh3gA=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alessio/shellescape v0.0.0-20190409004728-b115ca0f9053/go.mod h1:xW8sBma2LE3QxFSzCnH9qe6gAE2yO9GvQaWwX89HxbE=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis/v2 v2.11.1 h1:wuZ/ZHHELZ8DUF5sahK2T6V4Do2SdyKHnjrl/opkP8w=
github.com/alicebob/miniredis/v2 v2.11.1/go.mod h1:UA48pmi7aSazcGAvcdKcBB49z521IC9VjTTRz2nIaJE=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
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/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE=
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/calebcase/tmpfile v1.0.1 h1:vD8FSrbsbexhep39/6mvtbIHS3GzIRqiprDNCF6QqSk=
github.com/calebcase/tmpfile v1.0.1/go.mod h1:iErLeG/iqJr8LaQ/gYRv4GXdqssi3jg4iSzvrA06/lw=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cheggaaa/pb v1.0.5-0.20160713104425-73ae1d68fe0b h1:CMRCnhHx4xVxJy+wPsS67xmi9RHGNctLMoVn9Q1Kit8=
github.com/cheggaaa/pb v1.0.5-0.20160713104425-73ae1d68fe0b/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/cheggaaa/pb/v3 v3.0.1 h1:m0BngUk2LuSRYdx4fujDKNRXNDpbNCfptPfVT2m6OJY=
github.com/cheggaaa/pb/v3 v3.0.1/go.mod h1:SqqeMF/pMOIu3xgGoxtPYhMNQP258xE4x/XRTYua+KU=
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=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudfoundry/gosigar v1.1.0 h1:V/dVCzhKOdIU3WRB5inQU20s4yIgL9Dxx/Mhi0SF8eM=
github.com/cloudfoundry/gosigar v1.1.0/go.mod h1:3qLfc2GlfmwOx2+ZDaRGH3Y9fwQ0sQeaAleo2GV5pH0=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
github.com/containerd/containerd v1.2.7 h1:8lqLbl7u1j3MmiL9cJ/O275crSq7bfwUayvvatEupQk=
github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg=
github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc=
github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00/go.mod h1:olo7eAdKwJdXxb55TKGLiJ6xt1H0/tiiRCWKVLmtjY4=
github.com/cznic/lldb v1.1.0/go.mod h1:FIZVUmYUVhPwRiPzL8nD/mpFcJ/G7SSXjjXYG4uRI3A=
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE=
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8=
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-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
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=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dhui/dktest v0.3.0 h1:kwX5a7EkLcjo7VpsPQSYJcKGbXBXdjI9FGjuUj1jn6I=
github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc=
github.com/djherbis/atime v1.0.0 h1:ySLvBAM0EvOGaX7TI4dAM5lWj+RdJUCKtGSEHN8SGBg=
github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8=
github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU=
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v0.7.3-0.20190817195342-4760db040282 h1:mzrx39dGtGq0VEnTHjnakmczd4uFbhx2cZU3BJDsLdc=
github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
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/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/eclipse/paho.mqtt.golang v1.1.1 h1:iPJYXJLaViCshRTW/PSqImSS6HJ2Rf671WR0bXZ2GIU=
github.com/eclipse/paho.mqtt.golang v1.1.1/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU=
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fortytw2/leaktest v1.2.0 h1:cj6GCiwJDH7l3tMHLjZDo0QqPtrXJiWSI9JgpeQKw+Q=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
github.com/garyburd/redigo v1.0.1-0.20170216214944-0d253a66e6e1 h1:YmyuMm99D7kezPc0ZVWYnaUIWfMKR81lVVXttKTnDbw=
github.com/garyburd/redigo v1.0.1-0.20170216214944-0d253a66e6e1/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-ini/ini v1.52.0 h1:3UeUAveYUTCYV/G0jNDiIrrtIeAl1oAjshYyU2PaAlQ=
github.com/go-ini/ini v1.52.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.14.1+incompatible h1:kSJohAREGMr344uMa8PzuIg5OU6ylCbyDkWkkNOfEik=
github.com/go-redis/redis v6.14.1+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
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 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs=
github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.4.0 h1:XulKRWSQK5uChr4pEgSE4Tc/OcmnU9GJuSwdog/tZsA=
github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/rpc v1.1.0 h1:marKfvVP0Gpd/jHlVBKCQ8RAoUPdX7K1Nuh6l1BNh7A=
github.com/gorilla/rpc v1.1.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ=
github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/graphql-go/graphql v0.7.9-0.20190403165646-199d20bbfed7 h1:E45QFM7IqRdFnuyFk8GSamb42EckUSyJ55rtVB/w8VQ=
github.com/graphql-go/graphql v0.7.9-0.20190403165646-199d20bbfed7/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/raft v1.0.0 h1:htBVktAOtGs4Le5Z7K8SF5H2+oWsQFYVmOgH5loro7Y=
github.com/hashicorp/raft v1.0.0/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
github.com/jackc/pgx v3.2.0+incompatible h1:0Vihzu20St42/UDsvZGdNE6jak7oi/UOeMzwMPHkgFY=
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/go-luar v0.0.0-20170419063437-0786921db8c0/go.mod h1:OtVLEpPHGJkn8jgGrHlYELCA3uXLU0YSfNN0faeDM2M=
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3 h1:dITCBge70U9RDyZUL/Thn/yAT/ct4Rz40mNUX51dFCk=
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3/go.mod h1:eo5po8nCwRcvZIIR8eGi7PKthzXuunpXzUmXzxCBfBc=
github.com/jtolds/tracetagger/v2 v2.0.0-rc2 h1:pxmt5o+WRYffMwMYuFlI3wKwYbPVAyiX8EEyM8a/U7o=
github.com/jtolds/tracetagger/v2 v2.0.0-rc2/go.mod h1:EeqZ0b80feEwRK+FutrQ/GJxruNqamJBKOezZVfzSxA=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e h1:+lIPJOWl+jSiJOc70QXJ07+2eg2Jy2EC7Mi11BWujeM=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v0.0.0-20180704173009-925cb01d6510 h1:9eOgsI7EIGhJWPMBvSY+x0SEpeGGWUSijOrwK0XhpIk=
github.com/klauspost/reedsolomon v0.0.0-20180704173009-925cb01d6510/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/loov/hrtime v0.0.0-20181214195526-37a208e8344e/go.mod h1:2871C3urfEJnq/bpTYjFdMOdgxVd8otLLEL6vMNy/Iw=
github.com/loov/plot v0.0.0-20180510142208-e59891ae1271/go.mod h1:3yy5HBPbe5e1UmEffbO0n0g6A8h6ChHaCTeundr6H60=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5 h1:0x4qcEHDpruK6ML/m/YSlFUUu0UpRD3I2PHsNCuGnyA=
github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v2.0.2+incompatible h1:qzw9c2GNT8UFrgWNDhCTqRqYUSmu/Dav/9Z58LGpk7U=
github.com/mattn/go-sqlite3 v2.0.2+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/minio/cli v1.3.0 h1:vB0iUpmyaH54+1jJJj62Aa0qFF3xO3i0J3IcKiM6bHM=
github.com/minio/cli v1.3.0/go.mod h1:hLsWNQy2wIf3FKFnMlH69f4RdEyn8nbRA2shaulTjGY=
github.com/minio/dsync v0.0.0-20180124070302-439a0961af70 h1:pRHQdPOlUhelWqNUF3icFrBSC6VYH1hvF6HigVfgMoI=
github.com/minio/dsync v0.0.0-20180124070302-439a0961af70/go.mod h1:eLQe3mXL0h02kNpPtBJiLr1fIEIJftgXRAjncjQbxJo=
github.com/minio/highwayhash v0.0.0-20180501080913-85fc8a2dacad h1:L+8skVz2lusCbtlalLXmJp+TK8XaGAsZ3utSC3k5Jc0=
github.com/minio/highwayhash v0.0.0-20180501080913-85fc8a2dacad/go.mod h1:NL8wme5P5MoscwAkXfGroz3VgpCdhBw3KYOu5mEsvpU=
github.com/minio/lsync v0.0.0-20180328070428-f332c3883f63 h1:utJHim4C0K4CmD+Qgod/tgHvo7QNOlH6HN5O8QUvPEI=
github.com/minio/lsync v0.0.0-20180328070428-f332c3883f63/go.mod h1:ni10+iSX7FO8N2rv41XM444V6w4rYO0dZo5KIkbn/YA=
github.com/minio/mc v0.0.0-20180926130011-a215fbb71884 h1:co3kRW9cEI65yolYtcLcNxp2a9yk5T/eEt7gw14tJVs=
github.com/minio/mc v0.0.0-20180926130011-a215fbb71884/go.mod h1:pPcAoOwWUSIBqoLtp+0LEACUBUPhodkXwisyYrNgQ5o=
github.com/minio/minio v0.0.0-20180508161510-54cd29b51c38 h1:F7p0ZU9AQuxlA6SWwhXr0H/rYrA9fOiBk2OzOj7GtfM=
github.com/minio/minio v0.0.0-20180508161510-54cd29b51c38/go.mod h1:lXcp05uxYaW99ebgI6ZKIGYU7tqZkM5xSsG0xRt4VIU=
github.com/minio/minio-go v6.0.3+incompatible h1:yTq5mJOcWg6ot6STkEMnrNN896L0aDDu6njDB+8Ply0=
github.com/minio/minio-go v6.0.3+incompatible/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0 h1:ys4bbOlPvaUBlA0byjm6TqydsXZu614ZIUTfF+4MRY0=
github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0/go.mod h1:PDJGYr8GXjiOTIst0hQMOSK5FdXLwObr2cGbiMddDPc=
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/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
github.com/nats-io/gnatsd v1.3.0 h1:+5d80klu3QaJgNbdavVBjWJP7cHd11U2CLnRTFM9ICI=
github.com/nats-io/gnatsd v1.3.0/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
github.com/nats-io/go-nats v1.6.0 h1:FznPwMfrVwGnSCh7JTXyJDRW0TIkD4Tr+M1LPJt9T70=
github.com/nats-io/go-nats v1.6.0/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0=
github.com/nats-io/go-nats-streaming v0.4.2 h1:e7Fs4yxvFTs8N5xKFoJyw0sVW2heJwYvrUWfdf9VQlE=
github.com/nats-io/go-nats-streaming v0.4.2/go.mod h1:gfq4R3c9sKAINOpelo0gn/b9QDMBZnmrttcsNF+lqyo=
github.com/nats-io/nats v1.6.0 h1:U5b2apHOTZlUou+NGfCRWG4ZEeivbt2hpsZO4kHKIVU=
github.com/nats-io/nats v1.6.0/go.mod h1:PpmYZwlgTfBI56QypJLfIMOfLnMRuVs+VL6r8mQ2SoQ=
github.com/nats-io/nats-streaming-server v0.12.2 h1:EpyLfUBZgwu5c0mdSSytQsapm615AyitPssq7jgafdw=
github.com/nats-io/nats-streaming-server v0.12.2/go.mod h1:RyqtDJZvMZO66YmyjIYdIvS69zu/wDAkyNWa8PIUa5c=
github.com/nats-io/nuid v1.0.0 h1:44QGdhbiANq8ZCbUkdn6W5bqtg+mHuDE4wOUuxxndFs=
github.com/nats-io/nuid v1.0.0/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nsf/jsondiff v0.0.0-20160203110537-7de28ed2b6e3/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
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 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
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 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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-20190517135640-51af30a78b0e h1:zK8d1aZ+gw/Ne4uMfZTFRxj08PUOp+gGwm4HWUeGI1k=
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rs/cors v1.5.0 h1:dgSHE6+ia18arGOTIYQKKGWLvEbGvmbNE6NfxhoNHUY=
github.com/rs/cors v1.5.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad h1:EqOdoSJGI7CsBQczPcIgmpm3hJE7X8Hj3jrgI002whs=
github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad/go.mod h1:B3ehdD1xPoWDKgrQgUaGk+m8H1xb1J5TyYDfKpKNeEE=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114 h1:Pm6R878vxWWWR+Sa3ppsLce/Zq+JNTs6aVvRu13jv9A=
github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e h1:jrZSSgPUDtBeJbGXqgGUeupQH8I+ZvGXfhpIahye2Bc=
github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e/go.mod h1:d8hQseuYt4rJoOo21lFzYJdhMjmDqLY++ayArbgYjWI=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spacemonkeygo/errors v0.0.0-20171212215202-9064522e9fd1 h1:xHQewZjohU9/wUsyC99navCjQDNHtTgUOM/J1jAbzfw=
github.com/spacemonkeygo/errors v0.0.0-20171212215202-9064522e9fd1/go.mod h1:7NL9UAYQnRM5iKHUCld3tf02fKb5Dft+41+VckASUy0=
github.com/spacemonkeygo/monkit/v3 v3.0.0-20191108235033-eacca33b3037/go.mod h1:JcK1pCbReQsOsMKF/POFSZCq7drXFybgGmbc27tuwes=
github.com/spacemonkeygo/monkit/v3 v3.0.1 h1:mSZQU+LOFuN5KSUvE1EiU1lxlFcOz/r0N5Tz8z+TwN0=
github.com/spacemonkeygo/monkit/v3 v3.0.1/go.mod h1:JcK1pCbReQsOsMKF/POFSZCq7drXFybgGmbc27tuwes=
github.com/spacemonkeygo/monotime v0.0.0-20180824235756-e3f48a95f98a h1:8+cCjxhToanKmxLIbuyBNe2EnpgwhiivsIaRJstDRFA=
github.com/spacemonkeygo/monotime v0.0.0-20180824235756-e3f48a95f98a/go.mod h1:ul4bvvnCOPZgq8w0nTkSmWVg/hauVpFS97Am1YM1XXo=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/storj/grpc-go v1.23.1-0.20190918084400-1c4561bf5127 h1:sJtPW3g23UOuV+b5o3ARQ7467NzjjacUoBBPTyvIP9c=
github.com/storj/grpc-go v1.23.1-0.20190918084400-1c4561bf5127/go.mod h1:b+NmczNXvOWokHOVTM0zzTDhQEV+xRmnFVmFTVlkg8Q=
github.com/streadway/amqp v0.0.0-20180806233856-70e15c650864 h1:Oj3PUEs+OUSYUpn35O+BE/ivHGirKixA3+vqA0Atu9A=
github.com/streadway/amqp v0.0.0-20180806233856-70e15c650864/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY=
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/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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stripe/stripe-go v63.1.1+incompatible h1:OpGp55VzHcnu5O/MtVVU42xS2xeAWosx3xELvuoMMMw=
github.com/stripe/stripe-go v63.1.1+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY=
github.com/tidwall/gjson v1.1.3 h1:u4mspaByxY+Qk4U1QYYVzGFI8qxN/3jtEV0ZDb2vRic=
github.com/tidwall/gjson v1.1.3/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1 h1:pWIN9LOlFRCJFqWIOEbHLvY0WWJddsjH2FQ6N0HKZdU=
github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/vivint/infectious v0.0.0-20190108171102-2455b059135b h1:dLkqBELopfQNhe8S9ucnSf+HhiUCgK/hPIjVG0f9GlY=
github.com/vivint/infectious v0.0.0-20190108171102-2455b059135b/go.mod h1:5oyMAv4hrBEKqBwORFsiqIrCNCmL2qcZLQTdJLYeYIc=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583 h1:SZPG5w7Qxq7bMcMVl6e3Ht2X7f+AAGQdzjkbyOnNNZ8=
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/zeebo/admission/v2 v2.0.0 h1:220NPZzKmyfklysKFO95L7E2Gt5NwlxTWGE14VP8heE=
github.com/zeebo/admission/v2 v2.0.0/go.mod h1:gSeHGelDHW7Vq6UyJo2boeSt/6Dsnqpisv0i4YZSOyM=
github.com/zeebo/assert v0.0.0-20181109011804-10f827ce2ed6/go.mod h1:yssERNPivllc1yU3BvpjYI5BUW+zglcz6QWqeVRL5t0=
github.com/zeebo/assert v1.0.0/go.mod h1:yssERNPivllc1yU3BvpjYI5BUW+zglcz6QWqeVRL5t0=
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/errs v1.1.1/go.mod h1:Yj8dHrUQwls1bF3dr/vcSIu+qf4mI7idnTcHfoACc6I=
github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
github.com/zeebo/float16 v0.1.0 h1:kRqxv5og6z1emEyz5FpW0/BVHe5VfxEAw6b1ljCZlUc=
github.com/zeebo/float16 v0.1.0/go.mod h1:fssGvvXu+XS8MH57cKmyrLB/cqioYeYX/2mXCN3a5wo=
github.com/zeebo/incenc v0.0.0-20180505221441-0d92902eec54 h1:+cwNE5KJ3pika4HuzmDHkDlK5myo0G9Sv+eO7WWxnUQ=
github.com/zeebo/incenc v0.0.0-20180505221441-0d92902eec54/go.mod h1:EI8LcOBDlSL3POyqwC1eJhOYlMBMidES+613EtmmT5w=
github.com/zeebo/structs v1.0.2 h1:kvcd7s2LqXuO9cdV5LqrGHCOAfCBXaZpKCA3jD9SJIc=
github.com/zeebo/structs v1.0.2/go.mod h1:LphfpprlqJQcbCq+eA3iIK/NsejMwk9mlfH/tM1XuKQ=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
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=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
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=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-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-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200107144601-ef85f5a75ddf h1:9cZxTVBvFZgOnVi/DobY3JsafbPFPnP2rtN81d4wPpw=
golang.org/x/sys v0.0.0-20200107144601-ef85f5a75ddf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180917221912-90fa682c2a6e/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-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw=
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/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-20190716160619-c506a9f90610 h1:Ygq9/SRJX9+dU0WCIICM8RkWvDw03lvB77hrhJnpxfU=
google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
gopkg.in/Shopify/sarama.v1 v1.18.0 h1:f9aTXuIEFEjVvLG9p+kMSk01dMfFumHsySRk1okTdqU=
gopkg.in/Shopify/sarama.v1 v1.18.0/go.mod h1:AxnvoaevB2nBjNK17cG61A3LleFcWFwVBHBt+cot4Oc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.52.0 h1:j+Lt/M1oPPejkniCg1TkWE2J3Eh1oZTsHSXzMTzUXn4=
gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/olivere/elastic.v5 v5.0.76 h1:A6W7X4yLPQDINHiYAqIwqev+rD5hIQ4G0e1d5H//VXk=
gopkg.in/olivere/elastic.v5 v5.0.76/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
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/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
storj.io/common v0.0.0-20200214070817-cfd197b055d7/go.mod h1:MlYmhIuKHfD15puGH7Su5lv0bt4ojZ7IfrPnAmR4NeI=
storj.io/common v0.0.0-20200214110758-9e3820f574f6 h1:6Le0tbcmQDPYqWCiXRzd4fbp7ltpLaiPP6n6ZhEyguk=
storj.io/common v0.0.0-20200214110758-9e3820f574f6/go.mod h1:MlYmhIuKHfD15puGH7Su5lv0bt4ojZ7IfrPnAmR4NeI=
storj.io/common v0.0.0-20200221161141-79b008e3eff0 h1:lN5HVfeSa7uwbVYQ1CyQZ3I5nUeZzgejrGJZVjRsktg=
storj.io/common v0.0.0-20200221161141-79b008e3eff0/go.mod h1:lCc2baFO7GQlKsPTri8xwCsCPO2LsEUUiAGeRQuXY48=
storj.io/drpc v0.0.7-0.20191115031725-2171c57838d2/go.mod h1:/ascUDbzNAv0A3Jj7wUIKFBH2JdJ2uJIBO/b9+2yHgQ=
storj.io/drpc v0.0.8 h1:wu68cMmtoT0vSWIAZz29RpJkWdi4o0S8BIrLslpH5FQ=
storj.io/drpc v0.0.8/go.mod h1:v39uWro/EbXXk+gNnrM9FQuVVS2zUBWBfeduydgeXUA=
storj.io/gateway v0.0.0-20200221161528-36f00ab51fa7 h1:y9j0csaF76taOBELm3OrrBdyWsVkhYf2AyOfVqkngq8=
storj.io/gateway v0.0.0-20200221161528-36f00ab51fa7/go.mod h1:VtLc0oGOFi7Aslw33HG2nVibeyMBNNwYpiLRjE+O+rs=
storj.io/uplink v0.0.0-20200221135851-60db51e97359 h1:8IYCBjyXW4PAbhFhghZEXH8ZNbxD6lrfmNvotrD2G/E=
storj.io/uplink v0.0.0-20200221135851-60db51e97359/go.mod h1:SAetpjpLjDx0bH/TgfMaD2O/S283bn/Kcz8f/juI03I=
storj.io/uplink v0.0.0-20200221171743-26268cdd3552 h1:yXojx6mQXtJfwh5qdUEakWvh+EXkJbTV4qWE1aPJzTU=
storj.io/uplink v0.0.0-20200221171743-26268cdd3552/go.mod h1:SAetpjpLjDx0bH/TgfMaD2O/S283bn/Kcz8f/juI03I=

View File

@ -4,331 +4,7 @@
package main
import (
"context"
"crypto/rand"
"fmt"
"net"
"os"
"path/filepath"
"github.com/btcsuite/btcutil/base58"
"github.com/minio/cli"
minio "github.com/minio/minio/cmd"
"github.com/spf13/cobra"
"github.com/zeebo/errs"
"go.uber.org/zap"
"storj.io/common/fpath"
"storj.io/storj/cmd/internal/wizard"
"storj.io/storj/cmd/uplink/cmd"
"storj.io/storj/pkg/cfgstruct"
"storj.io/storj/pkg/miniogw"
"storj.io/storj/pkg/process"
"storj.io/storj/private/version"
"storj.io/storj/private/version/checker"
"storj.io/uplink"
"storj.io/gateway/private/cmd"
)
// GatewayFlags configuration flags
type GatewayFlags struct {
NonInteractive bool `help:"disable interactive mode" default:"false" setup:"true"`
Server miniogw.ServerConfig
Minio miniogw.MinioConfig
cmd.Config
Version checker.Config
PBKDFConcurrency int `help:"Unfortunately, up until v0.26.2, keys generated from passphrases depended on the number of cores the local CPU had. If you entered a passphrase with v0.26.2 earlier, you'll want to set this number to the number of CPU cores your computer had at the time. This flag may go away in the future. For new installations the default value is highly recommended." default:"0"`
}
var (
// Error is the default gateway setup errs class
Error = errs.Class("gateway setup error")
// rootCmd represents the base gateway command when called without any subcommands
rootCmd = &cobra.Command{
Use: "gateway",
Short: "The Storj client-side S3 gateway",
Args: cobra.OnlyValidArgs,
}
setupCmd = &cobra.Command{
Use: "setup",
Short: "Create a gateway config file",
RunE: cmdSetup,
Annotations: map[string]string{"type": "setup"},
}
runCmd = &cobra.Command{
Use: "run",
Short: "Run the S3 gateway",
RunE: cmdRun,
}
setupCfg GatewayFlags
runCfg GatewayFlags
confDir string
identityDir string
)
func init() {
defaultConfDir := fpath.ApplicationDir("storj", "gateway")
defaultIdentityDir := fpath.ApplicationDir("storj", "identity", "gateway")
cfgstruct.SetupFlag(zap.L(), rootCmd, &confDir, "config-dir", defaultConfDir, "main directory for gateway configuration")
cfgstruct.SetupFlag(zap.L(), rootCmd, &identityDir, "identity-dir", defaultIdentityDir, "main directory for gateway identity credentials")
defaults := cfgstruct.DefaultsFlag(rootCmd)
rootCmd.AddCommand(runCmd)
rootCmd.AddCommand(setupCmd)
process.Bind(runCmd, &runCfg, defaults, cfgstruct.ConfDir(confDir), cfgstruct.IdentityDir(identityDir))
process.Bind(setupCmd, &setupCfg, defaults, cfgstruct.ConfDir(confDir), cfgstruct.IdentityDir(identityDir), cfgstruct.SetupMode())
}
func cmdSetup(cmd *cobra.Command, args []string) (err error) {
setupDir, err := filepath.Abs(confDir)
if err != nil {
return Error.Wrap(err)
}
valid, _ := fpath.IsValidSetupDir(setupDir)
if !valid {
return Error.New("gateway configuration already exists (%v)", setupDir)
}
err = os.MkdirAll(setupDir, 0700)
if err != nil {
return Error.Wrap(err)
}
overrides := map[string]interface{}{}
accessKeyFlag := cmd.Flag("minio.access-key")
if !accessKeyFlag.Changed {
accessKey, err := generateKey()
if err != nil {
return err
}
overrides[accessKeyFlag.Name] = accessKey
}
secretKeyFlag := cmd.Flag("minio.secret-key")
if !secretKeyFlag.Changed {
secretKey, err := generateKey()
if err != nil {
return err
}
overrides[secretKeyFlag.Name] = secretKey
}
if setupCfg.NonInteractive {
return setupCfg.nonInteractive(cmd, setupDir, overrides)
}
return setupCfg.interactive(cmd, setupDir, overrides)
}
func cmdRun(cmd *cobra.Command, args []string) (err error) {
address := runCfg.Server.Address
host, port, err := net.SplitHostPort(address)
if err != nil {
return err
}
if host == "" {
address = net.JoinHostPort("127.0.0.1", port)
}
ctx, _ := process.Ctx(cmd)
if err := process.InitMetrics(ctx, zap.L(), nil, ""); err != nil {
zap.S().Warn("Failed to initialize telemetry batcher: ", err)
}
err = checker.CheckProcessVersion(ctx, zap.L(), runCfg.Version, version.Build, "Gateway")
if err != nil {
return err
}
zap.S().Infof("Starting Storj S3-compatible gateway!\n\n")
zap.S().Infof("Endpoint: %s\n", address)
zap.S().Infof("Access key: %s\n", runCfg.Minio.AccessKey)
zap.S().Infof("Secret key: %s\n", runCfg.Minio.SecretKey)
err = checkCfg(ctx)
if err != nil {
zap.S().Warn("Failed to contact Satellite. Perhaps your configuration is invalid?")
return err
}
return runCfg.Run(ctx)
}
func generateKey() (key string, err error) {
var buf [20]byte
_, err = rand.Read(buf[:])
if err != nil {
return "", Error.Wrap(err)
}
return base58.Encode(buf[:]), nil
}
func checkCfg(ctx context.Context) (err error) {
project, err := runCfg.openProject(ctx)
if err != nil {
return err
}
defer func() { err = errs.Combine(err, project.Close()) }()
buckets := project.ListBuckets(ctx, nil)
_ = buckets.Next()
return buckets.Err()
}
// Run starts a Minio Gateway given proper config
func (flags GatewayFlags) Run(ctx context.Context) (err error) {
err = minio.RegisterGatewayCommand(cli.Command{
Name: "storj",
Usage: "Storj",
Action: func(cliCtx *cli.Context) error {
return flags.action(ctx, cliCtx)
},
HideHelpCommand: true,
})
if err != nil {
return err
}
// TODO(jt): Surely there is a better way. This is so upsetting
err = os.Setenv("MINIO_ACCESS_KEY", flags.Minio.AccessKey)
if err != nil {
return err
}
err = os.Setenv("MINIO_SECRET_KEY", flags.Minio.SecretKey)
if err != nil {
return err
}
minio.Main([]string{"storj", "gateway", "storj",
"--address", flags.Server.Address, "--config-dir", flags.Minio.Dir, "--quiet"})
return errs.New("unexpected minio exit")
}
func (flags GatewayFlags) action(ctx context.Context, cliCtx *cli.Context) (err error) {
gw, err := flags.NewGateway(ctx)
if err != nil {
return err
}
minio.StartGateway(cliCtx, miniogw.Logging(gw, zap.L()))
return errs.New("unexpected minio exit")
}
// NewGateway creates a new minio Gateway
func (flags GatewayFlags) NewGateway(ctx context.Context) (gw minio.Gateway, err error) {
project, err := flags.openProject(ctx)
if err != nil {
return nil, err
}
return miniogw.NewStorjGateway(
project,
), nil
}
func (flags *GatewayFlags) newUplinkConfig(ctx context.Context) uplink.Config {
// Transform the gateway config flags to the uplink config object
uplinkCfg := uplink.Config{}
uplinkCfg.DialTimeout = flags.Client.DialTimeout
return uplinkCfg
}
func (flags GatewayFlags) openProject(ctx context.Context) (*uplink.Project, error) {
oldAccess, err := flags.GetAccess()
if err != nil {
return nil, Error.Wrap(err)
}
serializedAccess, err := oldAccess.Serialize()
if err != nil {
return nil, Error.Wrap(err)
}
access, err := uplink.ParseAccess(serializedAccess)
if err != nil {
return nil, Error.Wrap(err)
}
config := flags.newUplinkConfig(ctx)
project, err := config.OpenProject(ctx, access)
if err != nil {
return nil, Error.Wrap(err)
}
return project, nil
}
// interactive creates the configuration of the gateway interactively.
func (flags GatewayFlags) interactive(cmd *cobra.Command, setupDir string, overrides map[string]interface{}) error {
ctx, _ := process.Ctx(cmd)
satelliteAddress, err := wizard.PromptForSatellite(cmd)
if err != nil {
return Error.Wrap(err)
}
apiKey, err := wizard.PromptForAPIKey()
if err != nil {
return Error.Wrap(err)
}
passphrase, err := wizard.PromptForEncryptionPassphrase()
if err != nil {
return Error.Wrap(err)
}
access, err := uplink.RequestAccessWithPassphrase(ctx, satelliteAddress, apiKey, passphrase)
if err != nil {
return Error.Wrap(err)
}
accessData, err := access.Serialize()
if err != nil {
return Error.Wrap(err)
}
overrides["access"] = accessData
err = process.SaveConfig(cmd, filepath.Join(setupDir, "config.yaml"),
process.SaveConfigWithOverrides(overrides),
process.SaveConfigRemovingDeprecated())
if err != nil {
return Error.Wrap(err)
}
fmt.Println(`
Your S3 Gateway is configured and ready to use!
Some things to try next:
* See https://documentation.tardigrade.io/api-reference/s3-gateway for some example commands`)
return nil
}
// nonInteractive creates the configuration of the gateway non-interactively.
func (flags GatewayFlags) nonInteractive(cmd *cobra.Command, setupDir string, overrides map[string]interface{}) error {
// ensure we're using the access for the setup
access, err := setupCfg.GetAccess()
if err != nil {
return err
}
accessData, err := access.Serialize()
if err != nil {
return err
}
overrides["access"] = accessData
return Error.Wrap(process.SaveConfig(cmd, filepath.Join(setupDir, "config.yaml"),
process.SaveConfigWithOverrides(overrides),
process.SaveConfigRemovingDeprecated()))
}
func main() {
process.Exec(rootCmd)
}
func main() { cmd.Main() }

View File

@ -64,8 +64,9 @@ func main() {
default:
log.Println("unknown client name ", *clientName, " defaulting to minio")
fallthrough
case "minio":
client, err = s3client.NewMinio(conf)
// TODO: reenable
// case "minio":
// client, err = s3client.NewMinio(conf)
case "aws-cli":
client, err = s3client.NewAWSCLI(conf)
case "uplink":

58
go.mod
View File

@ -2,16 +2,7 @@ module storj.io/storj
go 1.13
// force specific versions for minio
require (
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a
github.com/garyburd/redigo v1.0.1-0.20170216214944-0d253a66e6e1 // indirect
github.com/graphql-go/graphql v0.7.9-0.20190403165646-199d20bbfed7
github.com/minio/minio v0.0.0-20180508161510-54cd29b51c38
github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad
)
exclude gopkg.in/olivere/elastic.v5 v5.0.72 // buggy import, see https://github.com/olivere/elastic/pull/869
require github.com/graphql-go/graphql v0.7.9-0.20190403165646-199d20bbfed7
replace google.golang.org/grpc => github.com/storj/grpc-go v1.23.1-0.20190918084400-1c4561bf5127
@ -20,79 +11,41 @@ require (
github.com/Shopify/go-lua v0.0.0-20181106184032-48449c60c0a9
github.com/alessio/shellescape v0.0.0-20190409004728-b115ca0f9053
github.com/alicebob/miniredis/v2 v2.11.1
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
github.com/blang/semver v3.5.1+incompatible
github.com/boltdb/bolt v1.3.1
github.com/cheggaaa/pb v1.0.5-0.20160713104425-73ae1d68fe0b // indirect
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a
github.com/cheggaaa/pb/v3 v3.0.1
github.com/djherbis/atime v1.0.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/eclipse/paho.mqtt.golang v1.1.1 // indirect
github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect
github.com/fatih/color v1.7.0
github.com/fatih/structs v1.0.0 // indirect
github.com/go-ini/ini v1.38.2 // indirect
github.com/go-redis/redis v6.14.1+incompatible
github.com/gogo/protobuf v1.2.1
github.com/golang-migrate/migrate/v4 v4.7.0
github.com/golang/protobuf v1.3.2
github.com/gomodule/redigo v2.0.0+incompatible // indirect
github.com/google/go-cmp v0.3.0
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/gorilla/handlers v1.4.0 // indirect
github.com/gorilla/mux v1.7.1
github.com/gorilla/rpc v1.1.0 // indirect
github.com/gorilla/schema v1.1.0
github.com/hashicorp/go-immutable-radix v1.0.0 // indirect
github.com/hashicorp/go-msgpack v0.5.3 // indirect
github.com/hashicorp/raft v1.0.0 // indirect
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c // indirect
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf // indirect
github.com/jackc/pgx v3.2.0+incompatible
github.com/jtolds/gls v4.2.1+incompatible // indirect
github.com/jtolds/go-luar v0.0.0-20170419063437-0786921db8c0
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3
github.com/jtolds/tracetagger/v2 v2.0.0-rc2
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e // indirect
github.com/klauspost/reedsolomon v0.0.0-20180704173009-925cb01d6510 // indirect
github.com/lib/pq v1.3.0
github.com/loov/hrtime v0.0.0-20181214195526-37a208e8344e
github.com/loov/plot v0.0.0-20180510142208-e59891ae1271
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/mattn/go-sqlite3 v2.0.2+incompatible
github.com/minio/cli v1.3.0
github.com/minio/dsync v0.0.0-20180124070302-439a0961af70 // indirect
github.com/minio/highwayhash v0.0.0-20180501080913-85fc8a2dacad // indirect
github.com/minio/lsync v0.0.0-20180328070428-f332c3883f63 // indirect
github.com/minio/mc v0.0.0-20180926130011-a215fbb71884 // indirect
github.com/minio/minio-go v6.0.3+incompatible
github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0 // indirect
github.com/nats-io/gnatsd v1.3.0 // indirect
github.com/nats-io/go-nats v1.6.0 // indirect
github.com/nats-io/go-nats-streaming v0.4.2 // indirect
github.com/nats-io/nats v1.6.0 // indirect
github.com/nats-io/nats-streaming-server v0.12.2 // indirect
github.com/nats-io/nuid v1.0.0 // indirect
github.com/nsf/jsondiff v0.0.0-20160203110537-7de28ed2b6e3
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c // indirect
github.com/pkg/profile v1.2.1 // indirect
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e // indirect
github.com/rs/cors v1.5.0 // indirect
github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad
github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114
github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e
github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf // indirect
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect
github.com/spacemonkeygo/monkit/v3 v3.0.1
github.com/spf13/cast v1.3.0
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.3
github.com/spf13/viper v1.4.0
github.com/streadway/amqp v0.0.0-20180806233856-70e15c650864 // indirect
github.com/stretchr/testify v1.4.0
github.com/stripe/stripe-go v63.1.1+incompatible
github.com/tidwall/gjson v1.1.3 // indirect
github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1 // indirect
github.com/vivint/infectious v0.0.0-20190108171102-2455b059135b
github.com/zeebo/admission/v2 v2.0.0
github.com/zeebo/errs v1.2.2
@ -102,12 +55,7 @@ require (
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/sys v0.0.0-20200107144601-ef85f5a75ddf
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
google.golang.org/appengine v1.6.0 // indirect
google.golang.org/grpc v1.23.1
gopkg.in/Shopify/sarama.v1 v1.18.0 // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.25 // indirect
gopkg.in/ini.v1 v1.38.2 // indirect
gopkg.in/olivere/elastic.v5 v5.0.76 // indirect
gopkg.in/yaml.v2 v2.2.4
storj.io/common v0.0.0-20200221161141-79b008e3eff0
storj.io/drpc v0.0.8

103
go.sum
View File

@ -26,8 +26,6 @@ github.com/alicebob/miniredis/v2 v2.11.1 h1:wuZ/ZHHELZ8DUF5sahK2T6V4Do2SdyKHnjrl
github.com/alicebob/miniredis/v2 v2.11.1/go.mod h1:UA48pmi7aSazcGAvcdKcBB49z521IC9VjTTRz2nIaJE=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
@ -43,8 +41,6 @@ github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+q
github.com/calebcase/tmpfile v1.0.1 h1:vD8FSrbsbexhep39/6mvtbIHS3GzIRqiprDNCF6QqSk=
github.com/calebcase/tmpfile v1.0.1/go.mod h1:iErLeG/iqJr8LaQ/gYRv4GXdqssi3jg4iSzvrA06/lw=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cheggaaa/pb v1.0.5-0.20160713104425-73ae1d68fe0b h1:CMRCnhHx4xVxJy+wPsS67xmi9RHGNctLMoVn9Q1Kit8=
github.com/cheggaaa/pb v1.0.5-0.20160713104425-73ae1d68fe0b/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/cheggaaa/pb/v3 v3.0.1 h1:m0BngUk2LuSRYdx4fujDKNRXNDpbNCfptPfVT2m6OJY=
github.com/cheggaaa/pb/v3 v3.0.1/go.mod h1:SqqeMF/pMOIu3xgGoxtPYhMNQP258xE4x/XRTYua+KU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -84,8 +80,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dhui/dktest v0.3.0 h1:kwX5a7EkLcjo7VpsPQSYJcKGbXBXdjI9FGjuUj1jn6I=
github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc=
github.com/djherbis/atime v1.0.0 h1:ySLvBAM0EvOGaX7TI4dAM5lWj+RdJUCKtGSEHN8SGBg=
github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8=
github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU=
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
@ -95,33 +89,19 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
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/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/eclipse/paho.mqtt.golang v1.1.1 h1:iPJYXJLaViCshRTW/PSqImSS6HJ2Rf671WR0bXZ2GIU=
github.com/eclipse/paho.mqtt.golang v1.1.1/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU=
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fortytw2/leaktest v1.2.0 h1:cj6GCiwJDH7l3tMHLjZDo0QqPtrXJiWSI9JgpeQKw+Q=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
github.com/garyburd/redigo v1.0.1-0.20170216214944-0d253a66e6e1 h1:YmyuMm99D7kezPc0ZVWYnaUIWfMKR81lVVXttKTnDbw=
github.com/garyburd/redigo v1.0.1-0.20170216214944-0d253a66e6e1/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-ini/ini v1.38.2 h1:6Hl/z3p3iFkA0dlDfzYxuFuUGD+kaweypF6btsR2/Q4=
github.com/go-ini/ini v1.38.2/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@ -163,16 +143,10 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.4.0 h1:XulKRWSQK5uChr4pEgSE4Tc/OcmnU9GJuSwdog/tZsA=
github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/rpc v1.1.0 h1:marKfvVP0Gpd/jHlVBKCQ8RAoUPdX7K1Nuh6l1BNh7A=
github.com/gorilla/rpc v1.1.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ=
github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@ -184,27 +158,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/raft v1.0.0 h1:htBVktAOtGs4Le5Z7K8SF5H2+oWsQFYVmOgH5loro7Y=
github.com/hashicorp/raft v1.0.0/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=
@ -214,8 +178,6 @@ github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGk
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/go-luar v0.0.0-20170419063437-0786921db8c0 h1:UyVaeqfY1fLPMt1iUTaWsxUNxYAzZVyK+7G+a3sRfhk=
github.com/jtolds/go-luar v0.0.0-20170419063437-0786921db8c0/go.mod h1:OtVLEpPHGJkn8jgGrHlYELCA3uXLU0YSfNN0faeDM2M=
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3 h1:dITCBge70U9RDyZUL/Thn/yAT/ct4Rz40mNUX51dFCk=
@ -226,10 +188,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e h1:+lIPJOWl+jSiJOc70QXJ07+2eg2Jy2EC7Mi11BWujeM=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v0.0.0-20180704173009-925cb01d6510 h1:9eOgsI7EIGhJWPMBvSY+x0SEpeGGWUSijOrwK0XhpIk=
github.com/klauspost/reedsolomon v0.0.0-20180704173009-925cb01d6510/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -249,8 +207,6 @@ github.com/loov/plot v0.0.0-20180510142208-e59891ae1271 h1:51ToN6N0TDtCruf681guf
github.com/loov/plot v0.0.0-20180510142208-e59891ae1271/go.mod h1:3yy5HBPbe5e1UmEffbO0n0g6A8h6ChHaCTeundr6H60=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5 h1:0x4qcEHDpruK6ML/m/YSlFUUu0UpRD3I2PHsNCuGnyA=
github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -263,24 +219,8 @@ github.com/mattn/go-sqlite3 v2.0.2+incompatible h1:qzw9c2GNT8UFrgWNDhCTqRqYUSmu/
github.com/mattn/go-sqlite3 v2.0.2+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/minio/cli v1.3.0 h1:vB0iUpmyaH54+1jJJj62Aa0qFF3xO3i0J3IcKiM6bHM=
github.com/minio/cli v1.3.0/go.mod h1:hLsWNQy2wIf3FKFnMlH69f4RdEyn8nbRA2shaulTjGY=
github.com/minio/dsync v0.0.0-20180124070302-439a0961af70 h1:pRHQdPOlUhelWqNUF3icFrBSC6VYH1hvF6HigVfgMoI=
github.com/minio/dsync v0.0.0-20180124070302-439a0961af70/go.mod h1:eLQe3mXL0h02kNpPtBJiLr1fIEIJftgXRAjncjQbxJo=
github.com/minio/highwayhash v0.0.0-20180501080913-85fc8a2dacad h1:L+8skVz2lusCbtlalLXmJp+TK8XaGAsZ3utSC3k5Jc0=
github.com/minio/highwayhash v0.0.0-20180501080913-85fc8a2dacad/go.mod h1:NL8wme5P5MoscwAkXfGroz3VgpCdhBw3KYOu5mEsvpU=
github.com/minio/lsync v0.0.0-20180328070428-f332c3883f63 h1:utJHim4C0K4CmD+Qgod/tgHvo7QNOlH6HN5O8QUvPEI=
github.com/minio/lsync v0.0.0-20180328070428-f332c3883f63/go.mod h1:ni10+iSX7FO8N2rv41XM444V6w4rYO0dZo5KIkbn/YA=
github.com/minio/mc v0.0.0-20180926130011-a215fbb71884 h1:co3kRW9cEI65yolYtcLcNxp2a9yk5T/eEt7gw14tJVs=
github.com/minio/mc v0.0.0-20180926130011-a215fbb71884/go.mod h1:pPcAoOwWUSIBqoLtp+0LEACUBUPhodkXwisyYrNgQ5o=
github.com/minio/minio v0.0.0-20180508161510-54cd29b51c38 h1:F7p0ZU9AQuxlA6SWwhXr0H/rYrA9fOiBk2OzOj7GtfM=
github.com/minio/minio v0.0.0-20180508161510-54cd29b51c38/go.mod h1:lXcp05uxYaW99ebgI6ZKIGYU7tqZkM5xSsG0xRt4VIU=
github.com/minio/minio-go v6.0.3+incompatible h1:yTq5mJOcWg6ot6STkEMnrNN896L0aDDu6njDB+8Ply0=
github.com/minio/minio-go v6.0.3+incompatible/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0 h1:ys4bbOlPvaUBlA0byjm6TqydsXZu614ZIUTfF+4MRY0=
github.com/minio/sio v0.0.0-20180327104954-6a41828a60f0/go.mod h1:PDJGYr8GXjiOTIst0hQMOSK5FdXLwObr2cGbiMddDPc=
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/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
@ -289,18 +229,6 @@ github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8d
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
github.com/nats-io/gnatsd v1.3.0 h1:+5d80klu3QaJgNbdavVBjWJP7cHd11U2CLnRTFM9ICI=
github.com/nats-io/gnatsd v1.3.0/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
github.com/nats-io/go-nats v1.6.0 h1:FznPwMfrVwGnSCh7JTXyJDRW0TIkD4Tr+M1LPJt9T70=
github.com/nats-io/go-nats v1.6.0/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0=
github.com/nats-io/go-nats-streaming v0.4.2 h1:e7Fs4yxvFTs8N5xKFoJyw0sVW2heJwYvrUWfdf9VQlE=
github.com/nats-io/go-nats-streaming v0.4.2/go.mod h1:gfq4R3c9sKAINOpelo0gn/b9QDMBZnmrttcsNF+lqyo=
github.com/nats-io/nats v1.6.0 h1:U5b2apHOTZlUou+NGfCRWG4ZEeivbt2hpsZO4kHKIVU=
github.com/nats-io/nats v1.6.0/go.mod h1:PpmYZwlgTfBI56QypJLfIMOfLnMRuVs+VL6r8mQ2SoQ=
github.com/nats-io/nats-streaming-server v0.12.2 h1:EpyLfUBZgwu5c0mdSSytQsapm615AyitPssq7jgafdw=
github.com/nats-io/nats-streaming-server v0.12.2/go.mod h1:RyqtDJZvMZO66YmyjIYdIvS69zu/wDAkyNWa8PIUa5c=
github.com/nats-io/nuid v1.0.0 h1:44QGdhbiANq8ZCbUkdn6W5bqtg+mHuDE4wOUuxxndFs=
github.com/nats-io/nuid v1.0.0/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nsf/jsondiff v0.0.0-20160203110537-7de28ed2b6e3 h1:OqFSgO6CJ8heZRAbXLpT+ojX+jnnGij4qZwUz/SJJ9I=
github.com/nsf/jsondiff v0.0.0-20160203110537-7de28ed2b6e3/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
@ -318,8 +246,6 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
@ -327,8 +253,6 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -346,14 +270,10 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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-20190517135640-51af30a78b0e h1:zK8d1aZ+gw/Ne4uMfZTFRxj08PUOp+gGwm4HWUeGI1k=
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rs/cors v1.5.0 h1:dgSHE6+ia18arGOTIYQKKGWLvEbGvmbNE6NfxhoNHUY=
github.com/rs/cors v1.5.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
@ -367,11 +287,6 @@ github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e h1:jrZSSgPUDtBeJbGXqgGUeupQH8I+ZvGXfhpIahye2Bc=
github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e/go.mod h1:d8hQseuYt4rJoOo21lFzYJdhMjmDqLY++ayArbgYjWI=
github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co=
github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo=
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spacemonkeygo/errors v0.0.0-20171212215202-9064522e9fd1 h1:xHQewZjohU9/wUsyC99navCjQDNHtTgUOM/J1jAbzfw=
github.com/spacemonkeygo/errors v0.0.0-20171212215202-9064522e9fd1/go.mod h1:7NL9UAYQnRM5iKHUCld3tf02fKb5Dft+41+VckASUy0=
@ -398,8 +313,6 @@ github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/storj/grpc-go v1.23.1-0.20190918084400-1c4561bf5127 h1:sJtPW3g23UOuV+b5o3ARQ7467NzjjacUoBBPTyvIP9c=
github.com/storj/grpc-go v1.23.1-0.20190918084400-1c4561bf5127/go.mod h1:b+NmczNXvOWokHOVTM0zzTDhQEV+xRmnFVmFTVlkg8Q=
github.com/streadway/amqp v0.0.0-20180806233856-70e15c650864 h1:Oj3PUEs+OUSYUpn35O+BE/ivHGirKixA3+vqA0Atu9A=
github.com/streadway/amqp v0.0.0-20180806233856-70e15c650864/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY=
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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@ -408,10 +321,6 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stripe/stripe-go v63.1.1+incompatible h1:OpGp55VzHcnu5O/MtVVU42xS2xeAWosx3xELvuoMMMw=
github.com/stripe/stripe-go v63.1.1+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY=
github.com/tidwall/gjson v1.1.3 h1:u4mspaByxY+Qk4U1QYYVzGFI8qxN/3jtEV0ZDb2vRic=
github.com/tidwall/gjson v1.1.3/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1 h1:pWIN9LOlFRCJFqWIOEbHLvY0WWJddsjH2FQ6N0HKZdU=
github.com/tidwall/match v0.0.0-20171002075945-1731857f09b1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@ -529,29 +438,19 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw=
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/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-20190716160619-c506a9f90610 h1:Ygq9/SRJX9+dU0WCIICM8RkWvDw03lvB77hrhJnpxfU=
google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
gopkg.in/Shopify/sarama.v1 v1.18.0 h1:f9aTXuIEFEjVvLG9p+kMSk01dMfFumHsySRk1okTdqU=
gopkg.in/Shopify/sarama.v1 v1.18.0/go.mod h1:AxnvoaevB2nBjNK17cG61A3LleFcWFwVBHBt+cot4Oc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.38.2 h1:dGcbywv4RufeGeiMycPT/plKB5FtmLKLnWKwBiLhUA4=
gopkg.in/ini.v1 v1.38.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/olivere/elastic.v5 v5.0.76 h1:A6W7X4yLPQDINHiYAqIwqev+rD5hIQ4G0e1d5H//VXk=
gopkg.in/olivere/elastic.v5 v5.0.76/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
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=
@ -571,7 +470,5 @@ storj.io/common v0.0.0-20200221161141-79b008e3eff0/go.mod h1:lCc2baFO7GQlKsPTri8
storj.io/drpc v0.0.7-0.20191115031725-2171c57838d2/go.mod h1:/ascUDbzNAv0A3Jj7wUIKFBH2JdJ2uJIBO/b9+2yHgQ=
storj.io/drpc v0.0.8 h1:wu68cMmtoT0vSWIAZz29RpJkWdi4o0S8BIrLslpH5FQ=
storj.io/drpc v0.0.8/go.mod h1:v39uWro/EbXXk+gNnrM9FQuVVS2zUBWBfeduydgeXUA=
storj.io/uplink v0.0.0-20200221135851-60db51e97359 h1:8IYCBjyXW4PAbhFhghZEXH8ZNbxD6lrfmNvotrD2G/E=
storj.io/uplink v0.0.0-20200221135851-60db51e97359/go.mod h1:SAetpjpLjDx0bH/TgfMaD2O/S283bn/Kcz8f/juI03I=
storj.io/uplink v0.0.0-20200221171743-26268cdd3552 h1:yXojx6mQXtJfwh5qdUEakWvh+EXkJbTV4qWE1aPJzTU=
storj.io/uplink v0.0.0-20200221171743-26268cdd3552/go.mod h1:SAetpjpLjDx0bH/TgfMaD2O/S283bn/Kcz8f/juI03I=

View File

@ -1,17 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package miniogw
// MinioConfig is a configuration struct that keeps details about starting
// Minio
type MinioConfig struct {
AccessKey string `help:"Minio Access Key to use" default:"insecure-dev-access-key"`
SecretKey string `help:"Minio Secret Key to use" default:"insecure-dev-secret-key"`
Dir string `help:"Minio generic server config path" default:"$CONFDIR/minio"`
}
// ServerConfig determines how minio listens for requests
type ServerConfig struct {
Address string `help:"address to serve S3 api over" default:"127.0.0.1:7777"`
}

View File

@ -1,476 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package miniogw
import (
"bytes"
"context"
"encoding/hex"
"io"
minio "github.com/minio/minio/cmd"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/hash"
"github.com/spacemonkeygo/monkit/v3"
"github.com/zeebo/errs"
"storj.io/common/storj"
"storj.io/uplink"
)
var (
mon = monkit.Package()
// Error is the errs class of standard End User Client errors
Error = errs.Class("Storj Gateway error")
)
// NewStorjGateway creates a new Storj S3 gateway.
func NewStorjGateway(project *uplink.Project) *Gateway {
return &Gateway{
project: project,
multipart: NewMultipartUploads(),
}
}
// Gateway is the implementation of a minio cmd.Gateway
type Gateway struct {
project *uplink.Project
multipart *MultipartUploads
}
// Name implements cmd.Gateway
func (gateway *Gateway) Name() string {
return "storj"
}
// NewGatewayLayer implements cmd.Gateway
func (gateway *Gateway) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, error) {
return &gatewayLayer{gateway: gateway}, nil
}
// Production implements cmd.Gateway
func (gateway *Gateway) Production() bool {
return false
}
type gatewayLayer struct {
minio.GatewayUnsupported
gateway *Gateway
}
func (layer *gatewayLayer) DeleteBucket(ctx context.Context, bucketName string) (err error) {
defer mon.Task()(&ctx)(&err)
_, err = layer.gateway.project.DeleteBucket(ctx, bucketName)
return convertError(err, bucketName, "")
}
func (layer *gatewayLayer) DeleteObject(ctx context.Context, bucketName, objectPath string) (err error) {
defer mon.Task()(&ctx)(&err)
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, bucketName)
if err != nil {
return convertError(err, bucketName, objectPath)
}
_, err = layer.gateway.project.DeleteObject(ctx, bucketName, objectPath)
return convertError(err, bucketName, objectPath)
}
func (layer *gatewayLayer) GetBucketInfo(ctx context.Context, bucketName string) (bucketInfo minio.BucketInfo, err error) {
defer mon.Task()(&ctx)(&err)
bucket, err := layer.gateway.project.StatBucket(ctx, bucketName)
if err != nil {
return minio.BucketInfo{}, convertError(err, bucketName, "")
}
return minio.BucketInfo{
Name: bucket.Name,
Created: bucket.Created,
}, nil
}
func (layer *gatewayLayer) GetObject(ctx context.Context, bucketName, objectPath string, startOffset int64, length int64, writer io.Writer, etag string) (err error) {
defer mon.Task()(&ctx)(&err)
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, bucketName)
if err != nil {
return convertError(err, bucketName, objectPath)
}
download, err := layer.gateway.project.DownloadObject(ctx, bucketName, objectPath, &uplink.DownloadOptions{
Offset: startOffset,
Length: length,
})
if err != nil {
return convertError(err, bucketName, objectPath)
}
defer func() { err = errs.Combine(err, download.Close()) }()
object := download.Info()
if startOffset < 0 || length < -1 || startOffset+length > object.Standard.ContentLength {
return minio.InvalidRange{
OffsetBegin: startOffset,
OffsetEnd: startOffset + length,
ResourceSize: object.Standard.ContentLength,
}
}
_, err = io.Copy(writer, download)
return err
}
func (layer *gatewayLayer) GetObjectInfo(ctx context.Context, bucketName, objectPath string) (objInfo minio.ObjectInfo, err error) {
defer mon.Task()(&ctx)(&err)
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, bucketName)
if err != nil {
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
object, err := layer.gateway.project.StatObject(ctx, bucketName, objectPath)
if err != nil {
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
return minioObjectInfo(bucketName, "", object), nil
}
func (layer *gatewayLayer) ListBuckets(ctx context.Context) (items []minio.BucketInfo, err error) {
defer mon.Task()(&ctx)(&err)
buckets := layer.gateway.project.ListBuckets(ctx, nil)
for buckets.Next() {
info := buckets.Item()
items = append(items, minio.BucketInfo{
Name: info.Name,
Created: info.Created,
})
}
if buckets.Err() != nil {
return nil, buckets.Err()
}
return items, nil
}
func (layer *gatewayLayer) ListObjects(ctx context.Context, bucketName, prefix, marker, delimiter string, maxKeys int) (result minio.ListObjectsInfo, err error) {
defer mon.Task()(&ctx)(&err)
// TODO maybe this should be checked by project.ListObjects
if bucketName == "" {
return minio.ListObjectsInfo{}, minio.BucketNameInvalid{}
}
if delimiter != "" && delimiter != "/" {
return minio.ListObjectsInfo{}, minio.UnsupportedDelimiter{Delimiter: delimiter}
}
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, bucketName)
if err != nil {
return result, convertError(err, bucketName, "")
}
list := layer.gateway.project.ListObjects(ctx, bucketName, &uplink.ListObjectsOptions{
Prefix: prefix,
Cursor: marker,
Recursive: delimiter == "",
Info: true,
Standard: true,
Custom: true,
})
startAfter := marker
var objects []minio.ObjectInfo
var prefixes []string
limit := maxKeys
for (limit > 0 || maxKeys == 0) && list.Next() {
limit--
object := list.Item()
if object.IsPrefix {
prefixes = append(prefixes, object.Key)
continue
}
objects = append(objects, minioObjectInfo(bucketName, "", object))
startAfter = object.Key
}
if list.Err() != nil {
return result, convertError(list.Err(), bucketName, "")
}
more := list.Next()
if list.Err() != nil {
return result, convertError(list.Err(), bucketName, "")
}
result = minio.ListObjectsInfo{
IsTruncated: more,
Objects: objects,
Prefixes: prefixes,
}
if more {
result.NextMarker = startAfter
}
return result, nil
}
func (layer *gatewayLayer) ListObjectsV2(ctx context.Context, bucketName, prefix, continuationToken, delimiter string, maxKeys int, fetchOwner bool, startAfter string) (result minio.ListObjectsV2Info, err error) {
defer mon.Task()(&ctx)(&err)
if delimiter != "" && delimiter != "/" {
return minio.ListObjectsV2Info{ContinuationToken: continuationToken}, minio.UnsupportedDelimiter{Delimiter: delimiter}
}
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, bucketName)
if err != nil {
return minio.ListObjectsV2Info{ContinuationToken: continuationToken}, convertError(err, bucketName, "")
}
recursive := delimiter == ""
var startAfterPath storj.Path
if continuationToken != "" {
startAfterPath = continuationToken
}
if startAfterPath == "" && startAfter != "" {
startAfterPath = startAfter
}
var objects []minio.ObjectInfo
var prefixes []string
list := layer.gateway.project.ListObjects(ctx, bucketName, &uplink.ListObjectsOptions{
Prefix: prefix,
Cursor: startAfterPath,
Recursive: recursive,
Info: true,
Standard: true,
Custom: true,
})
limit := maxKeys
for (limit > 0 || maxKeys == 0) && list.Next() {
limit--
object := list.Item()
if object.IsPrefix {
prefixes = append(prefixes, object.Key)
continue
}
objects = append(objects, minioObjectInfo(bucketName, "", object))
startAfter = object.Key
}
if list.Err() != nil {
return result, convertError(list.Err(), bucketName, "")
}
more := list.Next()
if list.Err() != nil {
return result, convertError(list.Err(), bucketName, "")
}
result = minio.ListObjectsV2Info{
IsTruncated: more,
ContinuationToken: startAfter,
Objects: objects,
Prefixes: prefixes,
}
if more {
result.NextContinuationToken = startAfter
}
return result, nil
}
func (layer *gatewayLayer) MakeBucketWithLocation(ctx context.Context, bucketName string, location string) (err error) {
defer mon.Task()(&ctx)(&err)
// TODO: maybe this should return an error since we don't support locations
_, err = layer.gateway.project.CreateBucket(ctx, bucketName)
return convertError(err, bucketName, "")
}
func (layer *gatewayLayer) CopyObject(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, srcInfo minio.ObjectInfo) (objInfo minio.ObjectInfo, err error) {
defer mon.Task()(&ctx)(&err)
if srcObject == "" {
return minio.ObjectInfo{}, minio.ObjectNameInvalid{Bucket: srcBucket}
}
if destObject == "" {
return minio.ObjectInfo{}, minio.ObjectNameInvalid{Bucket: destBucket}
}
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, srcBucket)
if err != nil {
return minio.ObjectInfo{}, convertError(err, srcBucket, "")
}
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, destBucket)
if err != nil {
return minio.ObjectInfo{}, convertError(err, destBucket, "")
}
download, err := layer.gateway.project.DownloadObject(ctx, srcBucket, srcObject, nil)
if err != nil {
return minio.ObjectInfo{}, convertError(err, srcBucket, srcObject)
}
defer func() {
// TODO: this hides minio error
err = errs.Combine(err, download.Close())
}()
upload, err := layer.gateway.project.UploadObject(ctx, destBucket, destObject, nil)
if err != nil {
return minio.ObjectInfo{}, convertError(err, destBucket, destObject)
}
info := download.Info()
err = upload.SetMetadata(ctx, &info.Standard, info.Custom)
if err != nil {
abortErr := upload.Abort()
err = errs.Combine(err, abortErr)
return minio.ObjectInfo{}, convertError(err, destBucket, destObject)
}
reader, err := hash.NewReader(download, info.Standard.ContentLength, "", "")
if err != nil {
abortErr := upload.Abort()
err = errs.Combine(err, abortErr)
return minio.ObjectInfo{}, convertError(err, destBucket, destObject)
}
_, err = io.Copy(upload, reader)
if err != nil {
abortErr := upload.Abort()
err = errs.Combine(err, abortErr)
return minio.ObjectInfo{}, convertError(err, destBucket, destObject)
}
err = upload.Commit()
if err != nil {
return minio.ObjectInfo{}, convertError(err, destBucket, destObject)
}
return minioObjectInfo(destBucket, hex.EncodeToString(reader.MD5Current()), upload.Info()), nil
}
func (layer *gatewayLayer) PutObject(ctx context.Context, bucketName, objectPath string, data *hash.Reader, metadata map[string]string) (objInfo minio.ObjectInfo, err error) {
defer mon.Task()(&ctx)(&err)
// TODO this should be removed and implemented on satellite side
_, err = layer.gateway.project.StatBucket(ctx, bucketName)
if err != nil {
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
if data == nil {
data, err = hash.NewReader(bytes.NewReader([]byte{}), 0, "", "")
if err != nil {
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
}
upload, err := layer.gateway.project.UploadObject(ctx, bucketName, objectPath, nil)
if err != nil {
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
n, err := io.Copy(upload, data)
if err != nil {
abortErr := upload.Abort()
err = errs.Combine(err, abortErr)
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
contentType := metadata["content-type"]
delete(metadata, "content-type")
err = upload.SetMetadata(ctx, &uplink.StandardMetadata{
ContentLength: n,
ContentType: contentType,
}, metadata)
if err != nil {
abortErr := upload.Abort()
err = errs.Combine(err, abortErr)
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
err = upload.Commit()
if err != nil {
return minio.ObjectInfo{}, convertError(err, bucketName, objectPath)
}
return minioObjectInfo(bucketName, data.MD5HexString(), upload.Info()), nil
}
func (layer *gatewayLayer) Shutdown(ctx context.Context) (err error) {
defer mon.Task()(&ctx)(&err)
return nil
}
func (layer *gatewayLayer) StorageInfo(context.Context) minio.StorageInfo {
return minio.StorageInfo{}
}
func convertError(err error, bucket, object string) error {
if uplink.ErrBucketNameInvalid.Has(err) {
return minio.BucketNameInvalid{Bucket: bucket}
}
if uplink.ErrBucketAlreadyExists.Has(err) {
return minio.BucketAlreadyExists{Bucket: bucket}
}
if uplink.ErrBucketNotFound.Has(err) {
return minio.BucketNotFound{Bucket: bucket}
}
if uplink.ErrBucketNotEmpty.Has(err) {
return minio.BucketNotEmpty{Bucket: bucket}
}
if uplink.ErrObjectKeyInvalid.Has(err) {
return minio.ObjectNameInvalid{Bucket: bucket, Object: object}
}
if uplink.ErrObjectNotFound.Has(err) {
return minio.ObjectNotFound{Bucket: bucket, Object: object}
}
return err
}
func minioObjectInfo(bucket, etag string, object *uplink.Object) minio.ObjectInfo {
return minio.ObjectInfo{
Bucket: bucket,
Name: object.Key,
Size: object.Standard.ContentLength,
ETag: etag,
ModTime: object.Info.Created,
ContentType: object.Standard.ContentType,
UserDefined: object.Custom,
}
}

View File

@ -1,799 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package miniogw_test
import (
"bytes"
"context"
"encoding/hex"
"fmt"
"io"
"strings"
"testing"
"time"
minio "github.com/minio/minio/cmd"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/hash"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zeebo/errs"
"storj.io/common/memory"
"storj.io/common/pb"
"storj.io/common/storj"
"storj.io/common/testcontext"
olduplink "storj.io/storj/lib/uplink"
"storj.io/storj/pkg/miniogw"
"storj.io/storj/private/testplanet"
"storj.io/uplink"
"storj.io/uplink/private/ecclient"
"storj.io/uplink/private/metainfo/kvmetainfo"
"storj.io/uplink/private/storage/segments"
"storj.io/uplink/private/storage/streams"
"storj.io/uplink/private/stream"
)
const (
TestEncKey = "test-encryption-key"
TestBucket = "test-bucket"
TestFile = "test-file"
DestBucket = "dest-bucket"
DestFile = "dest-file"
TestAPIKey = "test-api-key"
)
var (
defaultRS = storj.RedundancyScheme{
RequiredShares: 2,
RepairShares: 2,
OptimalShares: 3,
TotalShares: 4,
ShareSize: 256 * memory.B.Int32(),
}
defaultEP = storj.EncryptionParameters{
CipherSuite: storj.EncAESGCM,
BlockSize: defaultRS.StripeSize(),
}
defaultBucket = storj.Bucket{
PathCipher: storj.EncAESGCM,
DefaultRedundancyScheme: defaultRS,
DefaultEncryptionParameters: defaultEP,
}
)
func TestMakeBucketWithLocation(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when creating bucket with empty name
err := layer.MakeBucketWithLocation(ctx, "", "")
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Create a bucket with the Minio API
err = layer.MakeBucketWithLocation(ctx, TestBucket, "")
assert.NoError(t, err)
// Check that the bucket is created using the Metainfo API
bucket, err := m.GetBucket(ctx, TestBucket)
assert.NoError(t, err)
assert.Equal(t, TestBucket, bucket.Name)
assert.True(t, time.Since(bucket.Created) < 1*time.Minute)
assert.Equal(t, storj.EncAESGCM, bucket.PathCipher)
// Check the error when trying to create an existing bucket
err = layer.MakeBucketWithLocation(ctx, TestBucket, "")
assert.Equal(t, minio.BucketAlreadyExists{Bucket: TestBucket}, err)
})
}
func TestGetBucketInfo(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when getting info about bucket with empty name
_, err := layer.GetBucketInfo(ctx, "")
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when getting info about non-existing bucket
_, err = layer.GetBucketInfo(ctx, TestBucket)
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create the bucket using the Metainfo API
info, err := m.CreateBucket(ctx, TestBucket, &defaultBucket)
assert.NoError(t, err)
// Check the bucket info using the Minio API
bucket, err := layer.GetBucketInfo(ctx, TestBucket)
if assert.NoError(t, err) {
assert.Equal(t, TestBucket, bucket.Name)
assert.Equal(t, info.Created, bucket.Created)
}
})
}
func TestDeleteBucket(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when deleting bucket with empty name
err := layer.DeleteBucket(ctx, "")
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when deleting non-existing bucket
err = layer.DeleteBucket(ctx, TestBucket)
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create a bucket with a file using the Metainfo API
bucket, err := m.CreateBucket(ctx, TestBucket, &defaultBucket)
assert.NoError(t, err)
_, err = createFile(ctx, m, strms, bucket, TestFile, nil, nil)
assert.NoError(t, err)
// Check the error when deleting non-empty bucket
err = layer.DeleteBucket(ctx, TestBucket)
assert.Equal(t, minio.BucketNotEmpty{Bucket: TestBucket}, err)
// Delete the file using the Metainfo API, so the bucket becomes empty
err = m.DeleteObject(ctx, bucket, TestFile)
assert.NoError(t, err)
// Delete the bucket info using the Minio API
err = layer.DeleteBucket(ctx, TestBucket)
assert.NoError(t, err)
// Check that the bucket is deleted using the Metainfo API
_, err = m.GetBucket(ctx, TestBucket)
assert.True(t, storj.ErrBucketNotFound.Has(err))
})
}
func TestListBuckets(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check that empty list is return if no buckets exist yet
bucketInfos, err := layer.ListBuckets(ctx)
assert.NoError(t, err)
assert.Empty(t, bucketInfos)
// Create all expected buckets using the Metainfo API
bucketNames := []string{"bucket-1", "bucket-2", "bucket-3"}
buckets := make([]storj.Bucket, len(bucketNames))
for i, bucketName := range bucketNames {
bucket, err := m.CreateBucket(ctx, bucketName, &defaultBucket)
buckets[i] = bucket
assert.NoError(t, err)
}
// Check that the expected buckets can be listed using the Minio API
bucketInfos, err = layer.ListBuckets(ctx)
if assert.NoError(t, err) {
assert.Equal(t, len(bucketNames), len(bucketInfos))
for i, bucketInfo := range bucketInfos {
assert.Equal(t, bucketNames[i], bucketInfo.Name)
assert.Equal(t, buckets[i].Created, bucketInfo.Created)
}
}
})
}
func TestPutObject(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
data, err := hash.NewReader(bytes.NewReader([]byte("test")),
int64(len("test")),
"098f6bcd4621d373cade4e832627b4f6",
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")
require.NoError(t, err)
metadata := map[string]string{
"content-type": "media/foo",
"key1": "value1",
"key2": "value2",
}
serMetaInfo := pb.SerializableMeta{
ContentType: metadata["content-type"],
UserDefined: map[string]string{
"key1": metadata["key1"],
"key2": metadata["key2"],
},
}
// Check the error when putting an object to a bucket with empty name
_, err = layer.PutObject(ctx, "", "", nil, nil)
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when putting an object to a non-existing bucket
_, err = layer.PutObject(ctx, TestBucket, TestFile, nil, nil)
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create the bucket using the Metainfo API
testBucketInfo, err := m.CreateBucket(ctx, TestBucket, &defaultBucket)
assert.NoError(t, err)
// Check the error when putting an object with empty name
_, err = layer.PutObject(ctx, TestBucket, "", nil, nil)
assert.Equal(t, minio.ObjectNameInvalid{Bucket: TestBucket}, err)
// Put the object using the Minio API
info, err := layer.PutObject(ctx, TestBucket, TestFile, data, metadata)
if assert.NoError(t, err) {
assert.Equal(t, TestFile, info.Name)
assert.Equal(t, TestBucket, info.Bucket)
assert.False(t, info.IsDir)
assert.True(t, time.Since(info.ModTime) < 1*time.Minute)
assert.Equal(t, data.Size(), info.Size)
// assert.Equal(t, data.SHA256HexString(), info.ETag) TODO: when we start calculating checksums
assert.Equal(t, serMetaInfo.ContentType, info.ContentType)
assert.Equal(t, serMetaInfo.UserDefined, info.UserDefined)
}
// Check that the object is uploaded using the Metainfo API
obj, err := m.GetObjectExtended(ctx, testBucketInfo, TestFile)
if assert.NoError(t, err) {
assert.Equal(t, TestFile, obj.Path)
assert.Equal(t, TestBucket, obj.Bucket.Name)
assert.False(t, obj.IsPrefix)
// TODO upload.Info() is using StreamID creation time but this value is different
// than last segment creation time, CommitObject request should return latest info
// about object and those values should be used with upload.Info()
// This should be working after final fix
// assert.Equal(t, info.ModTime, obj.Info.Created)
assert.WithinDuration(t, info.ModTime, obj.Info.Created, 1*time.Second)
assert.Equal(t, info.Size, obj.Size)
// TODO disabled until we will store ETag with object
// assert.Equal(t, info.ETag, hex.EncodeToString(obj.Checksum))
assert.Equal(t, info.ContentType, obj.Standard.ContentType)
assert.Equal(t, info.UserDefined, obj.Custom)
}
})
}
func TestGetObjectInfo(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when getting an object from a bucket with empty name
_, err := layer.GetObjectInfo(ctx, "", "")
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when getting an object from non-existing bucket
_, err = layer.GetObjectInfo(ctx, TestBucket, TestFile)
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create the bucket using the Metainfo API
testBucketInfo, err := m.CreateBucket(ctx, TestBucket, &defaultBucket)
assert.NoError(t, err)
// Check the error when getting an object with empty name
_, err = layer.GetObjectInfo(ctx, TestBucket, "")
assert.Equal(t, minio.ObjectNameInvalid{Bucket: TestBucket}, err)
// Check the error when getting a non-existing object
_, err = layer.GetObjectInfo(ctx, TestBucket, TestFile)
assert.Equal(t, minio.ObjectNotFound{Bucket: TestBucket, Object: TestFile}, err)
// Create the object using the Metainfo API
createInfo := kvmetainfo.CreateObject{
ContentType: "text/plain",
Metadata: map[string]string{"key1": "value1", "key2": "value2"},
}
obj, err := createFile(ctx, m, strms, testBucketInfo, TestFile, &createInfo, []byte("test"))
assert.NoError(t, err)
// Get the object info using the Minio API
info, err := layer.GetObjectInfo(ctx, TestBucket, TestFile)
if assert.NoError(t, err) {
assert.Equal(t, TestFile, info.Name)
assert.Equal(t, TestBucket, info.Bucket)
assert.False(t, info.IsDir)
assert.Equal(t, obj.Created, info.ModTime)
assert.Equal(t, obj.Size, info.Size)
assert.Equal(t, hex.EncodeToString(obj.Checksum), info.ETag)
assert.Equal(t, createInfo.ContentType, info.ContentType)
assert.Equal(t, createInfo.Metadata, info.UserDefined)
}
})
}
func TestGetObject(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when getting an object from a bucket with empty name
err := layer.GetObject(ctx, "", "", 0, 0, nil, "")
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when getting an object from non-existing bucket
err = layer.GetObject(ctx, TestBucket, TestFile, 0, 0, nil, "")
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create the bucket using the Metainfo API
testBucketInfo, err := m.CreateBucket(ctx, TestBucket, &defaultBucket)
assert.NoError(t, err)
// Check the error when getting an object with empty name
err = layer.GetObject(ctx, TestBucket, "", 0, 0, nil, "")
assert.Equal(t, minio.ObjectNameInvalid{Bucket: TestBucket}, err)
// Check the error when getting a non-existing object
err = layer.GetObject(ctx, TestBucket, TestFile, 0, 0, nil, "")
assert.Equal(t, minio.ObjectNotFound{Bucket: TestBucket, Object: TestFile}, err)
// Create the object using the Metainfo API
createInfo := kvmetainfo.CreateObject{
ContentType: "text/plain",
Metadata: map[string]string{"key1": "value1", "key2": "value2"},
}
_, err = createFile(ctx, m, strms, testBucketInfo, TestFile, &createInfo, []byte("abcdef"))
assert.NoError(t, err)
for i, tt := range []struct {
offset, length int64
substr string
err error
}{
{offset: 0, length: 0, substr: ""},
{offset: 3, length: 0, substr: ""},
{offset: 0, length: -1, substr: "abcdef"},
{offset: 0, length: 6, substr: "abcdef"},
{offset: 0, length: 5, substr: "abcde"},
{offset: 0, length: 4, substr: "abcd"},
{offset: 1, length: 4, substr: "bcde"},
{offset: 2, length: 4, substr: "cdef"},
{offset: 0, length: 7, substr: "", err: minio.InvalidRange{OffsetBegin: 0, OffsetEnd: 7, ResourceSize: 6}},
{offset: -1, length: 7, substr: "", err: minio.InvalidRange{OffsetBegin: -1, OffsetEnd: 6, ResourceSize: 6}},
{offset: 0, length: -2, substr: "", err: minio.InvalidRange{OffsetBegin: 0, OffsetEnd: -2, ResourceSize: 6}},
} {
errTag := fmt.Sprintf("%d. %+v", i, tt)
var buf bytes.Buffer
// Get the object info using the Minio API
err = layer.GetObject(ctx, TestBucket, TestFile, tt.offset, tt.length, &buf, "")
if tt.err != nil {
assert.Equal(t, tt.err, err, errTag)
} else if assert.NoError(t, err) {
assert.Equal(t, tt.substr, buf.String(), errTag)
}
}
})
}
func TestCopyObject(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when copying an object from a bucket with empty name
_, err := layer.CopyObject(ctx, "", TestFile, DestBucket, DestFile, minio.ObjectInfo{})
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when copying an object from non-existing bucket
_, err = layer.CopyObject(ctx, TestBucket, TestFile, DestBucket, DestFile, minio.ObjectInfo{})
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create the source bucket using the Metainfo API
testBucketInfo, err := m.CreateBucket(ctx, TestBucket, &defaultBucket)
assert.NoError(t, err)
// Check the error when copying an object with empty name
_, err = layer.CopyObject(ctx, TestBucket, "", DestBucket, DestFile, minio.ObjectInfo{})
assert.Equal(t, minio.ObjectNameInvalid{Bucket: TestBucket}, err)
// Create the source object using the Metainfo API
createInfo := kvmetainfo.CreateObject{
ContentType: "text/plain",
Metadata: map[string]string{"key1": "value1", "key2": "value2"},
}
obj, err := createFile(ctx, m, strms, testBucketInfo, TestFile, &createInfo, []byte("test"))
assert.NoError(t, err)
// Get the source object info using the Minio API
srcInfo, err := layer.GetObjectInfo(ctx, TestBucket, TestFile)
assert.NoError(t, err)
// Check the error when copying an object to a bucket with empty name
_, err = layer.CopyObject(ctx, TestBucket, TestFile, "", DestFile, srcInfo)
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when copying an object to a non-existing bucket
_, err = layer.CopyObject(ctx, TestBucket, TestFile, DestBucket, DestFile, srcInfo)
assert.Equal(t, minio.BucketNotFound{Bucket: DestBucket}, err)
// Create the destination bucket using the Metainfo API
destBucketInfo, err := m.CreateBucket(ctx, DestBucket, &defaultBucket)
assert.NoError(t, err)
// Copy the object using the Minio API
info, err := layer.CopyObject(ctx, TestBucket, TestFile, DestBucket, DestFile, srcInfo)
if assert.NoError(t, err) {
assert.Equal(t, DestFile, info.Name)
assert.Equal(t, DestBucket, info.Bucket)
assert.False(t, info.IsDir)
assert.True(t, info.ModTime.Sub(obj.Modified) < 1*time.Minute)
assert.Equal(t, obj.Size, info.Size)
assert.Equal(t, createInfo.ContentType, info.ContentType)
assert.Equal(t, createInfo.Metadata, info.UserDefined)
}
// Check that the destination object is uploaded using the Metainfo API
obj, err = m.GetObject(ctx, destBucketInfo, DestFile)
if assert.NoError(t, err) {
assert.Equal(t, DestFile, obj.Path)
assert.Equal(t, DestBucket, obj.Bucket.Name)
assert.False(t, obj.IsPrefix)
// TODO upload.Info() is using StreamID creation time but this value is different
// than last segment creation time, CommitObject request should return latest info
// about object and those values should be used with upload.Info()
// This should be working after final fix
// assert.Equal(t, info.ModTime, obj.Info.Created)
assert.WithinDuration(t, info.ModTime, obj.Modified, 1*time.Second)
assert.Equal(t, info.Size, obj.Size)
assert.Equal(t, info.ContentType, obj.ContentType)
assert.Equal(t, info.UserDefined, obj.Metadata)
}
})
}
func TestDeleteObject(t *testing.T) {
runTest(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when deleting an object from a bucket with empty name
err := layer.DeleteObject(ctx, "", "")
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when deleting an object from non-existing bucket
err = layer.DeleteObject(ctx, TestBucket, TestFile)
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create the bucket using the Metainfo API
testBucketInfo, err := m.CreateBucket(ctx, TestBucket, &defaultBucket)
assert.NoError(t, err)
// Check the error when deleting an object with empty name
err = layer.DeleteObject(ctx, TestBucket, "")
assert.Equal(t, minio.ObjectNameInvalid{Bucket: TestBucket}, err)
// Check the error when deleting a non-existing object
err = layer.DeleteObject(ctx, TestBucket, TestFile)
assert.Equal(t, minio.ObjectNotFound{Bucket: TestBucket, Object: TestFile}, err)
// Create the object using the Metainfo API
_, err = createFile(ctx, m, strms, testBucketInfo, TestFile, nil, nil)
assert.NoError(t, err)
// Delete the object info using the Minio API
err = layer.DeleteObject(ctx, TestBucket, TestFile)
assert.NoError(t, err)
// Check that the object is deleted using the Metainfo API
_, err = m.GetObject(ctx, testBucketInfo, TestFile)
assert.True(t, storj.ErrObjectNotFound.Has(err))
})
}
func TestListObjects(t *testing.T) {
testListObjects(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, bucket, prefix, marker, delimiter string, maxKeys int) ([]string, []minio.ObjectInfo, bool, error) {
list, err := layer.ListObjects(ctx, TestBucket, prefix, marker, delimiter, maxKeys)
if err != nil {
return nil, nil, false, err
}
return list.Prefixes, list.Objects, list.IsTruncated, nil
})
}
func TestListObjectsV2(t *testing.T) {
testListObjects(t, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, bucket, prefix, marker, delimiter string, maxKeys int) ([]string, []minio.ObjectInfo, bool, error) {
list, err := layer.ListObjectsV2(ctx, TestBucket, prefix, marker, delimiter, maxKeys, false, "")
if err != nil {
return nil, nil, false, err
}
return list.Prefixes, list.Objects, list.IsTruncated, nil
})
}
func testListObjects(t *testing.T, listObjects func(*testing.T, context.Context, minio.ObjectLayer, string, string, string, string, int) ([]string, []minio.ObjectInfo, bool, error)) {
runTestWithPathCipher(t, storj.EncNull, func(t *testing.T, ctx context.Context, layer minio.ObjectLayer, m *kvmetainfo.DB, strms streams.Store) {
// Check the error when listing objects with unsupported delimiter
_, err := layer.ListObjects(ctx, TestBucket, "", "", "#", 0)
assert.Equal(t, minio.UnsupportedDelimiter{Delimiter: "#"}, err)
// Check the error when listing objects in a bucket with empty name
_, err = layer.ListObjects(ctx, "", "", "", "/", 0)
assert.Equal(t, minio.BucketNameInvalid{}, err)
// Check the error when listing objects in a non-existing bucket
_, err = layer.ListObjects(ctx, TestBucket, "", "", "", 0)
assert.Equal(t, minio.BucketNotFound{Bucket: TestBucket}, err)
// Create the bucket and files using the Metainfo API
testBucketInfo, err := m.CreateBucket(ctx, TestBucket, &storj.Bucket{
PathCipher: storj.EncNull,
DefaultRedundancyScheme: defaultRS,
DefaultEncryptionParameters: defaultEP,
})
assert.NoError(t, err)
filePaths := []string{
"a", "aa", "b", "bb", "c",
"a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc",
"b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc",
}
type expected struct {
object storj.Object
kvObject kvmetainfo.CreateObject
}
files := make(map[string]expected, len(filePaths))
createInfo := kvmetainfo.CreateObject{
ContentType: "text/plain",
Metadata: map[string]string{"key1": "value1", "key2": "value2"},
}
for _, filePath := range filePaths {
file, err := createFile(ctx, m, strms, testBucketInfo, filePath, &createInfo, []byte("test"))
files[filePath] = expected{
object: file,
kvObject: createInfo,
}
assert.NoError(t, err)
}
for i, tt := range []struct {
prefix string
marker string
delimiter string
maxKeys int
more bool
prefixes []string
objects []string
}{
{
delimiter: "/",
prefixes: []string{"a/", "b/"},
objects: []string{"a", "aa", "b", "bb", "c"},
}, {
marker: "`",
delimiter: "/",
prefixes: []string{"a/", "b/"},
objects: []string{"a", "aa", "b", "bb", "c"},
}, {
marker: "b",
delimiter: "/",
prefixes: []string{"b/"},
objects: []string{"bb", "c"},
}, {
marker: "c",
delimiter: "/",
}, {
marker: "ca",
delimiter: "/",
}, {
delimiter: "/",
maxKeys: 1,
more: true,
objects: []string{"a"},
}, {
marker: "`",
delimiter: "/",
maxKeys: 1,
more: true,
objects: []string{"a"},
}, {
marker: "aa",
delimiter: "/",
maxKeys: 1,
more: true,
objects: []string{"b"},
}, {
marker: "c",
delimiter: "/",
maxKeys: 1,
}, {
marker: "ca",
delimiter: "/",
maxKeys: 1,
}, {
delimiter: "/",
maxKeys: 2,
more: true,
prefixes: []string{"a/"},
objects: []string{"a"},
}, {
marker: "`",
delimiter: "/",
maxKeys: 2,
more: true,
prefixes: []string{"a/"},
objects: []string{"a"},
}, {
marker: "aa",
delimiter: "/",
maxKeys: 2,
more: true,
prefixes: []string{"b/"},
objects: []string{"b"},
}, {
marker: "bb",
delimiter: "/",
maxKeys: 2,
objects: []string{"c"},
}, {
marker: "c",
delimiter: "/",
maxKeys: 2,
}, {
marker: "ca",
delimiter: "/",
maxKeys: 2,
}, {
objects: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
}, {
prefix: "a/",
delimiter: "/",
objects: []string{"xa", "xaa", "xb", "xbb", "xc"},
}, {
prefix: "a/",
delimiter: "/",
objects: []string{"xa", "xaa", "xb", "xbb", "xc"},
}, {
prefix: "a/",
marker: "xb",
delimiter: "/",
objects: []string{"xbb", "xc"},
}, {
marker: "a/xbb",
maxKeys: 5,
more: true,
objects: []string{"a/xc", "aa", "b", "b/ya", "b/yaa"},
}, {
prefix: "a/",
marker: "xaa",
delimiter: "/",
maxKeys: 2,
more: true,
objects: []string{"xb", "xbb"},
},
} {
errTag := fmt.Sprintf("%d. %+v", i, tt)
// Check that the expected objects can be listed using the Minio API
prefixes, objects, isTruncated, err := listObjects(t, ctx, layer, TestBucket, tt.prefix, tt.marker, tt.delimiter, tt.maxKeys)
if assert.NoError(t, err, errTag) {
assert.Equal(t, tt.more, isTruncated, errTag)
assert.Equal(t, tt.prefixes, prefixes, errTag)
assert.Equal(t, len(tt.objects), len(objects), errTag)
for i, objectInfo := range objects {
path := objectInfo.Name
expected, found := files[path]
if assert.True(t, found) {
if tt.prefix != "" {
assert.Equal(t, storj.JoinPaths(strings.TrimSuffix(tt.prefix, "/"), tt.objects[i]), objectInfo.Name, errTag)
} else {
assert.Equal(t, tt.objects[i], objectInfo.Name, errTag)
}
assert.Equal(t, TestBucket, objectInfo.Bucket, errTag)
assert.False(t, objectInfo.IsDir, errTag)
assert.Equal(t, expected.object.Modified, objectInfo.ModTime, errTag)
assert.Equal(t, expected.object.Size, objectInfo.Size, errTag)
// assert.Equal(t, hex.EncodeToString(obj.Checksum), objectInfo.ETag, errTag)
assert.Equal(t, expected.kvObject.ContentType, objectInfo.ContentType, errTag)
assert.Equal(t, expected.kvObject.Metadata, objectInfo.UserDefined, errTag)
}
}
}
}
})
}
func runTest(t *testing.T, test func(*testing.T, context.Context, minio.ObjectLayer, *kvmetainfo.DB, streams.Store)) {
runTestWithPathCipher(t, storj.EncNull, test)
}
func runTestWithPathCipher(t *testing.T, pathCipher storj.CipherSuite, test func(*testing.T, context.Context, minio.ObjectLayer, *kvmetainfo.DB, streams.Store)) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1, StorageNodeCount: 4, UplinkCount: 1,
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
layer, m, strms, err := initEnv(ctx, t, planet, pathCipher)
require.NoError(t, err)
test(t, ctx, layer, m, strms)
})
}
func initEnv(ctx context.Context, t *testing.T, planet *testplanet.Planet, pathCipher storj.CipherSuite) (minio.ObjectLayer, *kvmetainfo.DB, streams.Store, error) {
apiKey := planet.Uplinks[0].APIKey[planet.Satellites[0].ID()]
m, err := planet.Uplinks[0].DialMetainfo(ctx, planet.Satellites[0], apiKey)
if err != nil {
return nil, nil, nil, err
}
// TODO(leak): close m metainfo.Client somehow
access, err := uplink.RequestAccessWithPassphrase(ctx, planet.Satellites[0].URL().String(), apiKey.Serialize(), "passphrase")
if err != nil {
return nil, nil, nil, err
}
serializedAccess, err := access.Serialize()
if err != nil {
return nil, nil, nil, err
}
oldAccess, err := olduplink.ParseScope(serializedAccess)
if err != nil {
return nil, nil, nil, err
}
oldAccess.EncryptionAccess.SetDefaultPathCipher(pathCipher)
encStore := oldAccess.EncryptionAccess.Store()
serializedOldAccess, err := oldAccess.Serialize()
if err != nil {
return nil, nil, nil, err
}
// workaround to set proper path cipher for uplink.Access
access, err = uplink.ParseAccess(serializedOldAccess)
if err != nil {
return nil, nil, nil, err
}
ec := ecclient.NewClient(planet.Uplinks[0].Log.Named("ecclient"), planet.Uplinks[0].Dialer, 0)
segments := segments.NewSegmentStore(m, ec)
blockSize := 1 * memory.KiB.Int()
inlineThreshold := 4 * memory.KiB.Int()
strms, err := streams.NewStreamStore(m, segments, 64*memory.MiB.Int64(), encStore, blockSize, storj.EncAESGCM, inlineThreshold, 8*memory.MiB.Int64())
if err != nil {
return nil, nil, nil, err
}
p, err := kvmetainfo.SetupProject(m)
if err != nil {
return nil, nil, nil, err
}
kvm := kvmetainfo.New(p, m, strms, segments, encStore)
project, err := uplink.OpenProject(ctx, access)
if err != nil {
return nil, nil, nil, err
}
gateway := miniogw.NewStorjGateway(project)
layer, err := gateway.NewGatewayLayer(auth.Credentials{})
if err != nil {
return nil, nil, nil, err
}
return layer, kvm, strms, err
}
func createFile(ctx context.Context, m *kvmetainfo.DB, strms streams.Store, bucket storj.Bucket, path storj.Path, createInfo *kvmetainfo.CreateObject, data []byte) (storj.Object, error) {
mutableObject, err := m.CreateObject(ctx, bucket, path, createInfo)
if err != nil {
return storj.Object{}, err
}
err = upload(ctx, strms, mutableObject, bytes.NewReader(data))
if err != nil {
return storj.Object{}, err
}
err = mutableObject.Commit(ctx)
if err != nil {
return storj.Object{}, err
}
return mutableObject.Info(), nil
}
func upload(ctx context.Context, streams streams.Store, mutableObject kvmetainfo.MutableObject, reader io.Reader) error {
mutableStream, err := mutableObject.CreateStream(ctx)
if err != nil {
return err
}
upload := stream.NewUpload(ctx, mutableStream, streams)
_, err = io.Copy(upload, reader)
return errs.Wrap(errs.Combine(err, upload.Close()))
}

View File

@ -1,162 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package miniogw_test
import (
"context"
"errors"
"flag"
"os"
"testing"
"time"
"github.com/minio/cli"
minio "github.com/minio/minio/cmd"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
"storj.io/common/identity"
"storj.io/common/identity/testidentity"
"storj.io/common/testcontext"
"storj.io/storj/cmd/uplink/cmd"
"storj.io/storj/pkg/miniogw"
"storj.io/storj/private/s3client"
"storj.io/storj/private/testplanet"
"storj.io/storj/satellite/console"
"storj.io/uplink"
)
type config struct {
Server miniogw.ServerConfig
Minio miniogw.MinioConfig
}
func TestUploadDownload(t *testing.T) {
t.Skip("disable because, keeps stalling CI intermittently")
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1, StorageNodeCount: 4, UplinkCount: 1,
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
// add project to satisfy constraint
_, err := planet.Satellites[0].DB.Console().Projects().Insert(ctx, &console.Project{
Name: "testProject",
})
require.NoError(t, err)
var gwCfg config
gwCfg.Minio.Dir = ctx.Dir("minio")
gwCfg.Server.Address = "127.0.0.1:7777"
uplinkCfg := planet.Uplinks[0].GetConfig(planet.Satellites[0])
planet.Start(ctx)
// create identity for gateway
ca, err := testidentity.NewTestCA(ctx)
assert.NoError(t, err)
identity, err := ca.NewIdentity()
assert.NoError(t, err)
// setup and start gateway
go func() {
// TODO: this leaks the gateway server, however it shouldn't
err := runGateway(ctx, gwCfg, uplinkCfg, zaptest.NewLogger(t), identity)
if err != nil {
t.Log(err)
}
}()
time.Sleep(100 * time.Millisecond)
client, err := s3client.NewMinio(s3client.Config{
S3Gateway: gwCfg.Server.Address,
Satellite: planet.Satellites[0].Addr(),
AccessKey: gwCfg.Minio.AccessKey,
SecretKey: gwCfg.Minio.SecretKey,
APIKey: uplinkCfg.Legacy.Client.APIKey,
EncryptionKey: "fake-encryption-key",
NoSSL: true,
})
assert.NoError(t, err)
bucket := "bucket"
err = client.MakeBucket(bucket, "")
assert.NoError(t, err)
// generate enough data for a remote segment
data := []byte{}
for i := 0; i < 5000; i++ {
data = append(data, 'a')
}
objectName := "testdata"
err = client.Upload(bucket, objectName, data)
assert.NoError(t, err)
buffer := make([]byte, len(data))
bytes, err := client.Download(bucket, objectName, buffer)
assert.NoError(t, err)
assert.Equal(t, string(data), string(bytes))
})
}
// runGateway creates and starts a gateway
func runGateway(ctx context.Context, gwCfg config, uplinkCfg cmd.Config, log *zap.Logger, ident *identity.FullIdentity) (err error) {
// set gateway flags
flags := flag.NewFlagSet("gateway", flag.ExitOnError)
flags.String("address", gwCfg.Server.Address, "")
flags.String("config-dir", gwCfg.Minio.Dir, "")
flags.Bool("quiet", true, "")
// create *cli.Context with gateway flags
cliCtx := cli.NewContext(cli.NewApp(), flags, nil)
// TODO: setting the flag on flagset and cliCtx seems redundant, but output is not quiet otherwise
err = cliCtx.Set("quiet", "true")
if err != nil {
return err
}
err = os.Setenv("MINIO_ACCESS_KEY", gwCfg.Minio.AccessKey)
if err != nil {
return err
}
err = os.Setenv("MINIO_SECRET_KEY", gwCfg.Minio.SecretKey)
if err != nil {
return err
}
oldAccess, err := uplinkCfg.GetAccess()
if err != nil {
return err
}
serializedAccess, err := oldAccess.Serialize()
if err != nil {
return err
}
access, err := uplink.ParseAccess(serializedAccess)
if err != nil {
return err
}
project, err := uplink.OpenProject(ctx, access)
if err != nil {
return err
}
gw := miniogw.NewStorjGateway(project)
minio.StartGateway(cliCtx, miniogw.Logging(gw, log))
return errors.New("unexpected minio exit")
}

View File

@ -1,208 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package miniogw
import (
"context"
"io"
"reflect"
"time"
minio "github.com/minio/minio/cmd"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/hash"
"github.com/minio/minio/pkg/madmin"
"github.com/minio/minio/pkg/policy"
"go.uber.org/zap"
)
type gatewayLogging struct {
gateway minio.Gateway
log *zap.Logger
}
// Logging returns a wrapper of minio.Gateway that logs errors before returning them.
func Logging(gateway minio.Gateway, log *zap.Logger) minio.Gateway {
return &gatewayLogging{gateway, log}
}
func (lg *gatewayLogging) Name() string { return lg.gateway.Name() }
func (lg *gatewayLogging) Production() bool { return lg.gateway.Production() }
func (lg *gatewayLogging) NewGatewayLayer(creds auth.Credentials) (minio.ObjectLayer, error) {
layer, err := lg.gateway.NewGatewayLayer(creds)
return &layerLogging{layer: layer, logger: lg.log}, err
}
type layerLogging struct {
layer minio.ObjectLayer
logger *zap.Logger
}
// minioError checks if the given error is a minio error.
func minioError(err error) bool {
return reflect.TypeOf(err).ConvertibleTo(reflect.TypeOf(minio.GenericError{}))
}
// log unexpected errors, i.e. non-minio errors. It will return the given error
// to allow method chaining.
func (log *layerLogging) log(err error) error {
if err != nil && !minioError(err) {
log.logger.Error("gateway error:", zap.Error(err))
}
return err
}
func (log *layerLogging) Shutdown(ctx context.Context) error {
return log.log(log.layer.Shutdown(ctx))
}
func (log *layerLogging) StorageInfo(ctx context.Context) minio.StorageInfo {
return log.layer.StorageInfo(ctx)
}
func (log *layerLogging) MakeBucketWithLocation(ctx context.Context, bucket string, location string) error {
return log.log(log.layer.MakeBucketWithLocation(ctx, bucket, location))
}
func (log *layerLogging) GetBucketInfo(ctx context.Context, bucket string) (bucketInfo minio.BucketInfo, err error) {
bucketInfo, err = log.layer.GetBucketInfo(ctx, bucket)
return bucketInfo, log.log(err)
}
func (log *layerLogging) ListBuckets(ctx context.Context) (buckets []minio.BucketInfo, err error) {
buckets, err = log.layer.ListBuckets(ctx)
return buckets, log.log(err)
}
func (log *layerLogging) DeleteBucket(ctx context.Context, bucket string) error {
return log.log(log.layer.DeleteBucket(ctx, bucket))
}
func (log *layerLogging) ListObjects(ctx context.Context, bucket, prefix, marker, delimiter string, maxKeys int) (result minio.ListObjectsInfo, err error) {
result, err = log.layer.ListObjects(ctx, bucket, prefix, marker, delimiter,
maxKeys)
return result, log.log(err)
}
func (log *layerLogging) ListObjectsV2(ctx context.Context, bucket, prefix, continuationToken, delimiter string, maxKeys int, fetchOwner bool, startAfter string) (result minio.ListObjectsV2Info, err error) {
result, err = log.layer.ListObjectsV2(ctx, bucket, prefix, continuationToken, delimiter, maxKeys, fetchOwner, startAfter)
return result, log.log(err)
}
func (log *layerLogging) GetObject(ctx context.Context, bucket, object string, startOffset int64, length int64, writer io.Writer, etag string) (err error) {
return log.log(log.layer.GetObject(ctx, bucket, object, startOffset, length, writer, etag))
}
func (log *layerLogging) GetObjectInfo(ctx context.Context, bucket, object string) (objInfo minio.ObjectInfo, err error) {
objInfo, err = log.layer.GetObjectInfo(ctx, bucket, object)
return objInfo, log.log(err)
}
func (log *layerLogging) PutObject(ctx context.Context, bucket, object string, data *hash.Reader, metadata map[string]string) (objInfo minio.ObjectInfo, err error) {
objInfo, err = log.layer.PutObject(ctx, bucket, object, data, metadata)
return objInfo, log.log(err)
}
func (log *layerLogging) CopyObject(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, srcInfo minio.ObjectInfo) (objInfo minio.ObjectInfo, err error) {
objInfo, err = log.layer.CopyObject(ctx, srcBucket, srcObject, destBucket, destObject, srcInfo)
return objInfo, log.log(err)
}
func (log *layerLogging) DeleteObject(ctx context.Context, bucket, object string) (err error) {
return log.log(log.layer.DeleteObject(ctx, bucket, object))
}
func (log *layerLogging) ListMultipartUploads(ctx context.Context, bucket, prefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (result minio.ListMultipartsInfo, err error) {
result, err = log.layer.ListMultipartUploads(ctx, bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads)
return result, log.log(err)
}
func (log *layerLogging) NewMultipartUpload(ctx context.Context, bucket, object string, metadata map[string]string) (uploadID string, err error) {
uploadID, err = log.layer.NewMultipartUpload(ctx, bucket, object, metadata)
return uploadID, log.log(err)
}
func (log *layerLogging) CopyObjectPart(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, uploadID string, partID int, startOffset int64, length int64, srcInfo minio.ObjectInfo) (info minio.PartInfo, err error) {
info, err = log.layer.CopyObjectPart(ctx, srcBucket, srcObject, destBucket, destObject, uploadID, partID, startOffset, length, srcInfo)
return info, log.log(err)
}
func (log *layerLogging) PutObjectPart(ctx context.Context, bucket, object, uploadID string, partID int, data *hash.Reader) (info minio.PartInfo, err error) {
info, err = log.layer.PutObjectPart(ctx, bucket, object, uploadID, partID, data)
return info, log.log(err)
}
func (log *layerLogging) ListObjectParts(ctx context.Context, bucket, object, uploadID string, partNumberMarker int, maxParts int) (result minio.ListPartsInfo, err error) {
result, err = log.layer.ListObjectParts(ctx, bucket, object, uploadID,
partNumberMarker, maxParts)
return result, log.log(err)
}
func (log *layerLogging) AbortMultipartUpload(ctx context.Context, bucket, object, uploadID string) error {
return log.log(log.layer.AbortMultipartUpload(ctx, bucket, object, uploadID))
}
func (log *layerLogging) CompleteMultipartUpload(ctx context.Context, bucket, object, uploadID string, uploadedParts []minio.CompletePart) (objInfo minio.ObjectInfo, err error) {
objInfo, err = log.layer.CompleteMultipartUpload(ctx, bucket, object, uploadID, uploadedParts)
return objInfo, log.log(err)
}
func (log *layerLogging) ReloadFormat(ctx context.Context, dryRun bool) error {
return log.log(log.layer.ReloadFormat(ctx, dryRun))
}
func (log *layerLogging) HealFormat(ctx context.Context, dryRun bool) (madmin.HealResultItem, error) {
rv, err := log.layer.HealFormat(ctx, dryRun)
return rv, log.log(err)
}
func (log *layerLogging) HealBucket(ctx context.Context, bucket string, dryRun bool) ([]madmin.HealResultItem, error) {
rv, err := log.layer.HealBucket(ctx, bucket, dryRun)
return rv, log.log(err)
}
func (log *layerLogging) HealObject(ctx context.Context, bucket, object string, dryRun bool) (madmin.HealResultItem, error) {
rv, err := log.layer.HealObject(ctx, bucket, object, dryRun)
return rv, log.log(err)
}
func (log *layerLogging) ListBucketsHeal(ctx context.Context) (buckets []minio.BucketInfo, err error) {
buckets, err = log.layer.ListBucketsHeal(ctx)
return buckets, log.log(err)
}
func (log *layerLogging) ListObjectsHeal(ctx context.Context, bucket, prefix, marker, delimiter string, maxKeys int) (minio.ListObjectsInfo, error) {
rv, err := log.layer.ListObjectsHeal(ctx, bucket, prefix, marker, delimiter, maxKeys)
return rv, log.log(err)
}
func (log *layerLogging) ListLocks(ctx context.Context, bucket, prefix string, duration time.Duration) ([]minio.VolumeLockInfo, error) {
rv, err := log.layer.ListLocks(ctx, bucket, prefix, duration)
return rv, log.log(err)
}
func (log *layerLogging) ClearLocks(ctx context.Context, lockInfos []minio.VolumeLockInfo) error {
return log.log(log.layer.ClearLocks(ctx, lockInfos))
}
func (log *layerLogging) SetBucketPolicy(ctx context.Context, n string, p *policy.Policy) error {
return log.log(log.layer.SetBucketPolicy(ctx, n, p))
}
func (log *layerLogging) GetBucketPolicy(ctx context.Context, n string) (*policy.Policy, error) {
p, err := log.layer.GetBucketPolicy(ctx, n)
return p, log.log(err)
}
func (log *layerLogging) DeleteBucketPolicy(ctx context.Context, n string) error {
return log.log(log.layer.DeleteBucketPolicy(ctx, n))
}
func (log *layerLogging) IsNotificationSupported() bool {
return log.layer.IsNotificationSupported()
}
func (log *layerLogging) IsEncryptionSupported() bool {
return log.layer.IsEncryptionSupported()
}

View File

@ -1,475 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package miniogw
import (
"context"
"io"
"sort"
"strconv"
"sync"
"sync/atomic"
"time"
minio "github.com/minio/minio/cmd"
"github.com/minio/minio/pkg/hash"
"github.com/zeebo/errs"
"storj.io/uplink"
)
func (layer *gatewayLayer) NewMultipartUpload(ctx context.Context, bucket, object string, metadata map[string]string) (uploadID string, err error) {
defer mon.Task()(&ctx)(&err)
uploads := layer.gateway.multipart
upload, err := uploads.Create(bucket, object, metadata)
if err != nil {
return "", err
}
// TODO: this can now be done without this separate goroutine
go func() {
stream, err := layer.gateway.project.UploadObject(ctx, bucket, object, nil)
if err != nil {
uploads.RemoveByID(upload.ID)
upload.fail(err)
return
}
// TODO: should we add prefixes to metadata?
// TODO: are there other fields we can extract to standard?
contentType := metadata["content-type"]
delete(metadata, "content-type")
err = stream.SetMetadata(ctx, &uplink.StandardMetadata{
ContentType: contentType,
}, metadata)
if err != nil {
uploads.RemoveByID(upload.ID)
abortErr := stream.Abort()
upload.fail(errs.Combine(err, abortErr))
return
}
_, err = io.Copy(stream, upload.Stream)
uploads.RemoveByID(upload.ID)
if err != nil {
abortErr := stream.Abort()
upload.fail(errs.Combine(err, abortErr))
return
}
err = stream.Commit()
if err != nil {
upload.fail(errs.Combine(err, err))
return
}
// TODO how set ETag here
upload.complete(minioObjectInfo(bucket, "", stream.Info()))
}()
return upload.ID, nil
}
func (layer *gatewayLayer) PutObjectPart(ctx context.Context, bucket, object, uploadID string, partID int, data *hash.Reader) (info minio.PartInfo, err error) {
defer mon.Task()(&ctx)(&err)
uploads := layer.gateway.multipart
upload, err := uploads.Get(bucket, object, uploadID)
if err != nil {
return minio.PartInfo{}, err
}
part, err := upload.Stream.AddPart(partID, data)
if err != nil {
return minio.PartInfo{}, err
}
err = <-part.Done
if err != nil {
return minio.PartInfo{}, err
}
partInfo := minio.PartInfo{
PartNumber: part.Number,
LastModified: time.Now(),
ETag: data.SHA256HexString(),
Size: atomic.LoadInt64(&part.Size),
}
upload.addCompletedPart(partInfo)
return partInfo, nil
}
func (layer *gatewayLayer) AbortMultipartUpload(ctx context.Context, bucket, object, uploadID string) (err error) {
defer mon.Task()(&ctx)(&err)
uploads := layer.gateway.multipart
upload, err := uploads.Remove(bucket, object, uploadID)
if err != nil {
return err
}
errAbort := Error.New("abort")
upload.Stream.Abort(errAbort)
r := <-upload.Done
if r.Error != errAbort {
return r.Error
}
return nil
}
func (layer *gatewayLayer) CompleteMultipartUpload(ctx context.Context, bucket, object, uploadID string, uploadedParts []minio.CompletePart) (objInfo minio.ObjectInfo, err error) {
defer mon.Task()(&ctx)(&err)
uploads := layer.gateway.multipart
upload, err := uploads.Remove(bucket, object, uploadID)
if err != nil {
return minio.ObjectInfo{}, err
}
// notify stream that there aren't more parts coming
upload.Stream.Close()
// wait for completion
result := <-upload.Done
// return the final info
return result.Info, result.Error
}
func (layer *gatewayLayer) ListObjectParts(ctx context.Context, bucket, object, uploadID string, partNumberMarker int, maxParts int) (result minio.ListPartsInfo, err error) {
defer mon.Task()(&ctx)(&err)
uploads := layer.gateway.multipart
upload, err := uploads.Get(bucket, object, uploadID)
if err != nil {
return minio.ListPartsInfo{}, err
}
list := minio.ListPartsInfo{}
list.Bucket = bucket
list.Object = object
list.UploadID = uploadID
list.PartNumberMarker = partNumberMarker
list.MaxParts = maxParts
list.UserDefined = upload.Metadata
list.Parts = upload.getCompletedParts()
sort.Slice(list.Parts, func(i, k int) bool {
return list.Parts[i].PartNumber < list.Parts[k].PartNumber
})
var first int
for i, p := range list.Parts {
first = i
if partNumberMarker <= p.PartNumber {
break
}
}
list.Parts = list.Parts[first:]
if len(list.Parts) > maxParts {
list.NextPartNumberMarker = list.Parts[maxParts].PartNumber
list.Parts = list.Parts[:maxParts]
list.IsTruncated = true
}
return list, nil
}
// TODO: implement
// func (layer *gatewayLayer) ListMultipartUploads(ctx context.Context, bucket, prefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (result minio.ListMultipartsInfo, err error) {
// func (layer *gatewayLayer) CopyObjectPart(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, uploadID string, partID int, startOffset int64, length int64, srcInfo minio.ObjectInfo) (info minio.PartInfo, err error) {
// MultipartUploads manages pending multipart uploads
type MultipartUploads struct {
mu sync.RWMutex
lastID int
pending map[string]*MultipartUpload
}
// NewMultipartUploads creates new MultipartUploads
func NewMultipartUploads() *MultipartUploads {
return &MultipartUploads{
pending: map[string]*MultipartUpload{},
}
}
// Create creates a new upload
func (uploads *MultipartUploads) Create(bucket, object string, metadata map[string]string) (*MultipartUpload, error) {
uploads.mu.Lock()
defer uploads.mu.Unlock()
for id, upload := range uploads.pending {
if upload.Bucket == bucket && upload.Object == object {
upload.Stream.Abort(Error.New("aborted by another upload to the same location"))
delete(uploads.pending, id)
}
}
uploads.lastID++
uploadID := "Upload" + strconv.Itoa(uploads.lastID)
upload := NewMultipartUpload(uploadID, bucket, object, metadata)
uploads.pending[uploadID] = upload
return upload, nil
}
// Get finds a pending upload
func (uploads *MultipartUploads) Get(bucket, object, uploadID string) (*MultipartUpload, error) {
uploads.mu.Lock()
defer uploads.mu.Unlock()
upload, ok := uploads.pending[uploadID]
if !ok {
return nil, Error.New("pending upload %q missing", uploadID)
}
if upload.Bucket != bucket || upload.Object != object {
return nil, Error.New("pending upload %q bucket/object name mismatch", uploadID)
}
return upload, nil
}
// Remove returns and removes a pending upload
func (uploads *MultipartUploads) Remove(bucket, object, uploadID string) (*MultipartUpload, error) {
uploads.mu.RLock()
defer uploads.mu.RUnlock()
upload, ok := uploads.pending[uploadID]
if !ok {
return nil, Error.New("pending upload %q missing", uploadID)
}
if upload.Bucket != bucket || upload.Object != object {
return nil, Error.New("pending upload %q bucket/object name mismatch", uploadID)
}
delete(uploads.pending, uploadID)
return upload, nil
}
// RemoveByID removes pending upload by id
func (uploads *MultipartUploads) RemoveByID(uploadID string) {
uploads.mu.RLock()
defer uploads.mu.RUnlock()
delete(uploads.pending, uploadID)
}
// MultipartUpload is partial info about a pending upload
type MultipartUpload struct {
ID string
Bucket string
Object string
Metadata map[string]string
Done chan (*MultipartUploadResult)
Stream *MultipartStream
mu sync.Mutex
completed []minio.PartInfo
}
// MultipartUploadResult contains either an Error or the uploaded ObjectInfo
type MultipartUploadResult struct {
Error error
Info minio.ObjectInfo
}
// NewMultipartUpload creates a new MultipartUpload
func NewMultipartUpload(uploadID string, bucket, object string, metadata map[string]string) *MultipartUpload {
upload := &MultipartUpload{
ID: uploadID,
Bucket: bucket,
Object: object,
Metadata: metadata,
Done: make(chan *MultipartUploadResult, 1),
Stream: NewMultipartStream(),
}
return upload
}
// addCompletedPart adds a completed part to the list
func (upload *MultipartUpload) addCompletedPart(part minio.PartInfo) {
upload.mu.Lock()
defer upload.mu.Unlock()
upload.completed = append(upload.completed, part)
}
func (upload *MultipartUpload) getCompletedParts() []minio.PartInfo {
upload.mu.Lock()
defer upload.mu.Unlock()
return append([]minio.PartInfo{}, upload.completed...)
}
// fail aborts the upload with an error
func (upload *MultipartUpload) fail(err error) {
upload.Done <- &MultipartUploadResult{Error: err}
close(upload.Done)
}
// complete completes the upload
func (upload *MultipartUpload) complete(info minio.ObjectInfo) {
upload.Done <- &MultipartUploadResult{Info: info}
close(upload.Done)
}
// MultipartStream serializes multiple readers into a single reader
type MultipartStream struct {
mu sync.Mutex
moreParts sync.Cond
err error
closed bool
finished bool
nextID int
nextNumber int
currentPart *StreamPart
parts []*StreamPart
}
// StreamPart is a reader waiting in MultipartStream
type StreamPart struct {
Number int
ID int
Size int64
Reader *hash.Reader
Done chan error
}
// NewMultipartStream creates a new MultipartStream
func NewMultipartStream() *MultipartStream {
stream := &MultipartStream{}
stream.moreParts.L = &stream.mu
stream.nextID = 1
return stream
}
// Abort aborts the stream reading
func (stream *MultipartStream) Abort(err error) {
stream.mu.Lock()
defer stream.mu.Unlock()
if stream.finished {
return
}
if stream.err == nil {
stream.err = err
}
stream.finished = true
stream.closed = true
for _, part := range stream.parts {
part.Done <- err
close(part.Done)
}
stream.parts = nil
stream.moreParts.Broadcast()
}
// Close closes the stream, but lets it complete
func (stream *MultipartStream) Close() {
stream.mu.Lock()
defer stream.mu.Unlock()
stream.closed = true
stream.moreParts.Broadcast()
}
// Read implements io.Reader interface, blocking when there's no part
func (stream *MultipartStream) Read(data []byte) (n int, err error) {
stream.mu.Lock()
for {
// has an error occurred?
if stream.err != nil {
stream.mu.Unlock()
return 0, Error.Wrap(err)
}
// still uploading the current part?
if stream.currentPart != nil {
break
}
// do we have the next part?
if len(stream.parts) > 0 && stream.nextID == stream.parts[0].ID {
stream.currentPart = stream.parts[0]
stream.parts = stream.parts[1:]
stream.nextID++
break
}
// we don't have the next part and are closed, hence we are complete
if stream.closed {
stream.finished = true
stream.mu.Unlock()
return 0, io.EOF
}
stream.moreParts.Wait()
}
stream.mu.Unlock()
// read as much as we can
n, err = stream.currentPart.Reader.Read(data)
atomic.AddInt64(&stream.currentPart.Size, int64(n))
if err == io.EOF {
// the part completed, hence advance to the next one
err = nil
close(stream.currentPart.Done)
stream.currentPart = nil
} else if err != nil {
// something bad happened, abort the whole thing
stream.Abort(err)
return n, Error.Wrap(err)
}
return n, err
}
// AddPart adds a new part to the stream to wait
func (stream *MultipartStream) AddPart(partID int, data *hash.Reader) (*StreamPart, error) {
stream.mu.Lock()
defer stream.mu.Unlock()
if partID < stream.nextID {
return nil, Error.New("part %d already uploaded, next part ID is %d", partID, stream.nextID)
}
for _, p := range stream.parts {
if p.ID == partID {
// Replace the reader of this part with the new one.
// This could happen if the read timeout for this part has expired
// and the client tries to upload the part again.
p.Reader = data
return p, nil
}
}
stream.nextNumber++
part := &StreamPart{
Number: stream.nextNumber - 1,
ID: partID,
Size: 0,
Reader: data,
Done: make(chan error, 1),
}
stream.parts = append(stream.parts, part)
sort.Slice(stream.parts, func(i, k int) bool {
return stream.parts[i].ID < stream.parts[k].ID
})
stream.moreParts.Broadcast()
return part, nil
}

View File

@ -1,6 +1,11 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
// This is disabled for the time-being to allow removing minio dependencies from
// storj.io/storj package.
// +build ignore
package s3client
import (

View File

@ -99,7 +99,7 @@ install_sim(){
go install -race -v -o ${bin_dir}/storj-sim storj.io/storj/cmd/storj-sim >/dev/null 2>&1
go install -race -v -o ${bin_dir}/versioncontrol storj.io/storj/cmd/versioncontrol >/dev/null 2>&1
go install -race -v -o ${bin_dir}/uplink storj.io/storj/cmd/uplink >/dev/null 2>&1
go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
cd ${scriptdir}/../../../cmd/gateway && go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
go install -race -v -o ${bin_dir}/identity storj.io/storj/cmd/identity >/dev/null 2>&1
go install -race -v -o ${bin_dir}/certificates storj.io/storj/cmd/certificates >/dev/null 2>&1
@ -179,6 +179,8 @@ fi
echo "Setting up environments for versions" ${unique_versions}
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
# Get latest release tags and clean up git worktree
git worktree prune
for version in ${unique_versions}; do
@ -218,10 +220,10 @@ for version in ${unique_versions}; do
mkdir -p ${bin_dir}
# uncomment for Jenkins testing:
go install -race -v -o ${bin_dir}/uplink storj.io/storj/cmd/uplink >/dev/null 2>&1
go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
cd ${scriptdir}/../../../cmd/gateway && go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
# uncomment for local testing:
# GOBIN=${bin_dir} go install -race -v storj.io/storj/cmd/uplink > /dev/null 2>&1
# GOBIN=${bin_dir} go install -race -v storj.io/storj/cmd/gateway > /dev/null 2>&1
# GOBIN=${bin_dir} cd ${scriptdir}/../../../cmd/gateway && go install -race -v storj.io/storj/cmd/gateway > /dev/null 2>&1
popd
echo "Finished installing. ${bin_dir}:" $(ls ${bin_dir})
echo "Binary shasums:"
@ -236,7 +238,6 @@ done
test_dir=$(version_dir "test_dir")
cp -r $(version_dir ${stage1_sat_version}) ${test_dir}
echo -e "\nSetting up stage 1 in ${test_dir}"
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
test_versions_path="$( dirname "${scriptdir}" )/testversions/test-versions.sh"
setup_stage "${test_dir}" "${stage1_sat_version}" "${stage1_storagenode_versions}" "1"

View File

@ -62,6 +62,8 @@ replace_in_file(){
esac
}
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
# mirroring install-sim from the Makefile since it won't work on private Jenkins
install_sim(){
local bin_dir="$1"
@ -72,7 +74,7 @@ install_sim(){
go install -race -v -o ${bin_dir}/storj-sim storj.io/storj/cmd/storj-sim >/dev/null 2>&1
go install -race -v -o ${bin_dir}/versioncontrol storj.io/storj/cmd/versioncontrol >/dev/null 2>&1
go install -race -v -o ${bin_dir}/uplink storj.io/storj/cmd/uplink >/dev/null 2>&1
go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
cd ${scriptdir}/../../../cmd/gateway && go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
go install -race -v -o ${bin_dir}/identity storj.io/storj/cmd/identity >/dev/null 2>&1
go install -race -v -o ${bin_dir}/certificates storj.io/storj/cmd/certificates >/dev/null 2>&1
@ -178,10 +180,10 @@ for version in ${unique_versions}; do
pushd ${dir}
mkdir -p ${bin_dir}
go install -race -v -o ${bin_dir}/uplink storj.io/storj/cmd/uplink >/dev/null 2>&1
go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
cd ${scriptdir}/../../../cmd/gateway && go install -race -v -o ${bin_dir}/gateway storj.io/storj/cmd/gateway >/dev/null 2>&1
# uncomment for local testing
# GOBIN=${bin_dir} go install -race -v storj.io/storj/cmd/uplink >/dev/null 2>&1
# GOBIN=${bin_dir} go install -race -v storj.io/storj/cmd/gateway >/dev/null 2>&1
# GOBIN=${bin_dir} cd ${scriptdir}/../../../cmd/gateway && go install -race -v storj.io/storj/cmd/gateway >/dev/null 2>&1
popd
echo "Finished installing. ${bin_dir}:" $(ls ${bin_dir})
echo "Binary shasums:"
@ -207,7 +209,6 @@ done
test_dir=$(version_dir "test_dir")
cp -r $(version_dir ${stage1_sat_version}) ${test_dir}
echo -e "\nSetting up stage 1 in ${test_dir}"
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
setup_stage "${test_dir}" "${stage1_sat_version}" "${stage1_storagenode_versions}"
# Uploading files to the network using the latest release version for each uplink version