Upgrade minio-go to version 7

This commit is contained in:
Lena Fuhrimann 2021-08-05 11:44:40 +02:00
parent 07c0c2d9f7
commit 2499415fea
24 changed files with 274 additions and 206 deletions

View file

@ -18,4 +18,4 @@ jobs:
with: with:
args: release --rm-dist args: release --rm-dist
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

6
.gitignore vendored
View file

@ -1,14 +1,16 @@
# Binaries for programs and plugins # Binaries for programs and plugins
bin/
dist/
*.exe *.exe
*.exe~ *.exe~
*.dll *.dll
*.so *.so
*.dylib *.dylib
bin/
# Test binary, build with `go test -c` # Test binary, build with `go test -c`
*.test *.test
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out
# Dependency directories (remove the comment below to include it)
# vendor/

View file

@ -14,15 +14,10 @@ lint:
test: test:
go test -race -cover ./... go test -race -cover ./...
.PHONY: build-docker .PHONY: build-image
build-docker: build-image:
docker build -t s3manager . docker build -t s3manager .
.PHONY: deploy-cf
deploy-cf:
GOOS=linux go build -ldflags="-s -w" -o bin/s3manager
cf push -f deployments/cf/manifest.yml
.PHONY: clean .PHONY: clean
clean: clean:
rm -rf bin rm -rf bin

View file

@ -15,6 +15,7 @@ A Web GUI written in Go to manage S3 buckets from any provider.
The application can be configured with the following environment variables: The application can be configured with the following environment variables:
- `ENDPOINT`: The endpoint of your S3 server (defaults to `s3.amazonaws.com`) - `ENDPOINT`: The endpoint of your S3 server (defaults to `s3.amazonaws.com`)
- `REGION`: The region of your S3 server (defaults to `""`)
- `ACCESS_KEY_ID`: Your S3 access key ID (required) - `ACCESS_KEY_ID`: Your S3 access key ID (required)
- `SECRET_ACCESS_KEY`: Your S3 secret access key (required) - `SECRET_ACCESS_KEY`: Your S3 secret access key (required)
- `USE_SSL`: Whether your S3 server uses SSL or not (defaults to `true`) - `USE_SSL`: Whether your S3 server uses SSL or not (defaults to `true`)
@ -26,15 +27,10 @@ The application can be configured with the following environment variables:
1. Run `make build` 1. Run `make build`
1. Execute the created binary and visit <http://localhost:8080> 1. Execute the created binary and visit <http://localhost:8080>
### Run Docker image ### Run Container image
1. Run `docker run -p 8080:8080 -e 'ACCESS_KEY_ID=XXX' -e 'SECRET_ACCESS_KEY=xxx' mastertinner/s3manager` 1. Run `docker run -p 8080:8080 -e 'ACCESS_KEY_ID=XXX' -e 'SECRET_ACCESS_KEY=xxx' mastertinner/s3manager`
### Deploy to Cloud Foundry
1. Modify `deployments/cf/*` to your liking
1. Run `make deploy-cf`
## Development ## Development
### Lint Code ### Lint Code
@ -45,11 +41,11 @@ The application can be configured with the following environment variables:
1. Run `make test` 1. Run `make test`
### Build Docker Image ### Build Container Image
The image is available on [Docker Hub](https://hub.docker.com/r/mastertinner/s3manager/) The image is available on [Docker Hub](https://hub.docker.com/r/mastertinner/s3manager/)
1. Run `make build-docker` 1. Run `make build-image`
### Run Locally for Testing ### Run Locally for Testing

View file

@ -1,26 +0,0 @@
#!/bin/bash
set -e -u
if [ -z "${PORT}" ]; then
echo "Error: No PORT found" >&2
exit 1
fi
if [ -z "${VCAP_SERVICES}" ]; then
echo "Error: No VCAP_SERVICES found" >&2
exit 1
fi
# S3
s3_credentials="$(echo "${VCAP_SERVICES}" | jq -r '.["dynstrg"][0].credentials // ""')"
if [ -z "${s3_credentials}" ]; then
echo "Error: Please bind an S3 service" >&2
exit 1
fi
s3_endpoint="$(echo "${s3_credentials}" | jq -r '.accessHost // ""')"
s3_endpoint="${s3_endpoint#'https://'}"
s3_access_key_id="$(echo "${s3_credentials}" | jq -r '.accessKey // ""')"
s3_secret_access_key="$(echo "${s3_credentials}" | jq -r '.sharedSecret // ""')"
# Run binary
ENDPOINT="${s3_endpoint}" ACCESS_KEY_ID="${s3_access_key_id}" SECRET_ACCESS_KEY="${s3_secret_access_key}" ./s3manager

View file

@ -1,8 +0,0 @@
applications:
- name: s3-manager
buildpacks:
- https://github.com/cloudfoundry/binary-buildpack.git
memory: 64M
command: ./deployments/cf/entrypoint.sh
services:
- my-storage

20
go.mod
View file

@ -3,15 +3,23 @@ module github.com/mastertinner/s3manager
go 1.16 go 1.16
require ( require (
github.com/go-ini/ini v1.62.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20210803090616-8f023c250c89 // indirect github.com/gopherjs/gopherjs v0.0.0-20210803090616-8f023c250c89 // indirect
github.com/mastertinner/adapters v0.0.0-20210601115127-f9c5f1df5ec2 github.com/json-iterator/go v1.1.11 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/mastertinner/adapters v0.0.0-20210813140839-f946b3f928f1
github.com/matryer/is v1.4.0 github.com/matryer/is v1.4.0
github.com/matryer/way v0.0.0-20180416093233-9632d0c407b0 github.com/matryer/way v0.0.0-20180416093233-9632d0c407b0
github.com/minio/minio-go v6.0.14+incompatible github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.12
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/rs/xid v1.3.0 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect github.com/smartystreets/assertions v1.2.0 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect github.com/stretchr/testify v1.7.0 // indirect
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
golang.org/x/sys v0.0.0-20210817133320-13f9c583af74 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )

70
go.sum
View file

@ -58,9 +58,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 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/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@ -72,14 +75,13 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ini/ini v1.62.0 h1:7VJT/ZXjzqSrvtraFp4ONq80hTcRQth1c9ZnQ3uNQvU=
github.com/go-ini/ini v1.62.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 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.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -116,6 +118,7 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -126,6 +129,9 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@ -159,6 +165,9 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@ -166,14 +175,21 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
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.1/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/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mastertinner/adapters v0.0.0-20210601115127-f9c5f1df5ec2 h1:1xj8GPMA06VxvfKVUa3W1za7/eODStJG3lYWIYqypTo= github.com/mastertinner/adapters v0.0.0-20210813140839-f946b3f928f1 h1:ZPvesDqKoVIeQFkfikuck4ILJTFUrRv5wV36bzSBQs8=
github.com/mastertinner/adapters v0.0.0-20210601115127-f9c5f1df5ec2/go.mod h1:CLHlHgTXdyVYGucevVppiRddQVtVop2ORWbgSXObP0I= github.com/mastertinner/adapters v0.0.0-20210813140839-f946b3f928f1/go.mod h1:2wARZp3HPycyJvAbmX3k6ufim3fpiEJLqGUmNYuVUHA=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/matryer/way v0.0.0-20180416093233-9632d0c407b0 h1:KWiqy3hl8yCUPAq1frD0DKXKyn7d9h2nVhj2r5ISq2o= github.com/matryer/way v0.0.0-20180416093233-9632d0c407b0 h1:KWiqy3hl8yCUPAq1frD0DKXKyn7d9h2nVhj2r5ISq2o=
@ -182,8 +198,14 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/minio-go v6.0.14+incompatible h1:fnV+GD28LeqdN6vT2XdGKW8Qe/IfjJDswNVuni6km9o= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/minio-go v6.0.14+incompatible/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.12 h1:/4pxUdwn9w0QEryNkrrWaodIESPRX+NxpO0Q6hVdaAA=
github.com/minio/minio-go/v7 v7.0.12/go.mod h1:S23iSP5/gbMwtxeY5FM71R+TkAYyzEdoNEDDwpt8yWs=
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@ -193,7 +215,11 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
@ -203,6 +229,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -217,6 +244,9 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@ -225,6 +255,8 @@ github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJ
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@ -244,6 +276,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
@ -267,9 +301,10 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e h1:VvfwVmMH40bpMeizC9/K7ipM5Qjucuu16RWfneFPyhQ=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -332,8 +367,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -366,6 +401,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -380,6 +416,7 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -387,16 +424,18 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210817133320-13f9c583af74 h1:b3RvH1NpRl6xu9OF46sZVLhjgJ0G7DteZbCC5zFknyY=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817133320-13f9c583af74/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -527,6 +566,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
@ -534,7 +574,11 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View file

@ -8,7 +8,7 @@ import (
"path" "path"
"github.com/matryer/way" "github.com/matryer/way"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
// HandleBucketView shows the details page of a bucket. // HandleBucketView shows the details page of a bucket.
@ -29,7 +29,7 @@ func HandleBucketView(s3 S3, templates fs.FS) http.HandlerFunc {
var objs []objectWithIcon var objs []objectWithIcon
doneCh := make(chan struct{}) doneCh := make(chan struct{})
defer close(doneCh) defer close(doneCh)
objectCh := s3.ListObjectsV2(bucketName, "", true, doneCh) objectCh := s3.ListObjects(r.Context(), bucketName, minio.ListObjectsOptions{})
for object := range objectCh { for object := range objectCh {
if object.Err != nil { if object.Err != nil {
handleHTTPError(w, fmt.Errorf("error listing objects: %w", object.Err)) handleHTTPError(w, fmt.Errorf("error listing objects: %w", object.Err))

View file

@ -1,6 +1,7 @@
package s3manager_test package s3manager_test
import ( import (
"context"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -14,7 +15,7 @@ import (
"github.com/mastertinner/s3manager/internal/app/s3manager/mocks" "github.com/mastertinner/s3manager/internal/app/s3manager/mocks"
"github.com/matryer/is" "github.com/matryer/is"
"github.com/matryer/way" "github.com/matryer/way"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
func TestHandleBucketView(t *testing.T) { func TestHandleBucketView(t *testing.T) {
@ -22,14 +23,14 @@ func TestHandleBucketView(t *testing.T) {
cases := []struct { cases := []struct {
it string it string
listObjectsV2Func func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo listObjectsFunc func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo
bucketName string bucketName string
expectedStatusCode int expectedStatusCode int
expectedBodyContains string expectedBodyContains string
}{ }{
{ {
it: "renders a bucket containing a file", it: "renders a bucket containing a file",
listObjectsV2Func: func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { listObjectsFunc: func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objCh := make(chan minio.ObjectInfo) objCh := make(chan minio.ObjectInfo)
go func() { go func() {
objCh <- minio.ObjectInfo{Key: "testFile"} objCh <- minio.ObjectInfo{Key: "testFile"}
@ -43,7 +44,7 @@ func TestHandleBucketView(t *testing.T) {
}, },
{ {
it: "renders placeholder for an empty bucket", it: "renders placeholder for an empty bucket",
listObjectsV2Func: func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { listObjectsFunc: func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objCh := make(chan minio.ObjectInfo) objCh := make(chan minio.ObjectInfo)
close(objCh) close(objCh)
return objCh return objCh
@ -54,7 +55,7 @@ func TestHandleBucketView(t *testing.T) {
}, },
{ {
it: "renders a bucket containing an archive", it: "renders a bucket containing an archive",
listObjectsV2Func: func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { listObjectsFunc: func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objCh := make(chan minio.ObjectInfo) objCh := make(chan minio.ObjectInfo)
go func() { go func() {
objCh <- minio.ObjectInfo{Key: "archive.tar.gz"} objCh <- minio.ObjectInfo{Key: "archive.tar.gz"}
@ -68,7 +69,7 @@ func TestHandleBucketView(t *testing.T) {
}, },
{ {
it: "renders a bucket containing an image", it: "renders a bucket containing an image",
listObjectsV2Func: func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { listObjectsFunc: func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objCh := make(chan minio.ObjectInfo) objCh := make(chan minio.ObjectInfo)
go func() { go func() {
objCh <- minio.ObjectInfo{Key: "testImage.png"} objCh <- minio.ObjectInfo{Key: "testImage.png"}
@ -82,7 +83,7 @@ func TestHandleBucketView(t *testing.T) {
}, },
{ {
it: "renders a bucket containing a sound file", it: "renders a bucket containing a sound file",
listObjectsV2Func: func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { listObjectsFunc: func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objCh := make(chan minio.ObjectInfo) objCh := make(chan minio.ObjectInfo)
go func() { go func() {
objCh <- minio.ObjectInfo{Key: "testSound.mp3"} objCh <- minio.ObjectInfo{Key: "testSound.mp3"}
@ -96,7 +97,7 @@ func TestHandleBucketView(t *testing.T) {
}, },
{ {
it: "returns error if the bucket doesn't exist", it: "returns error if the bucket doesn't exist",
listObjectsV2Func: func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { listObjectsFunc: func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objCh := make(chan minio.ObjectInfo) objCh := make(chan minio.ObjectInfo)
go func() { go func() {
objCh <- minio.ObjectInfo{Err: errBucketDoesNotExist} objCh <- minio.ObjectInfo{Err: errBucketDoesNotExist}
@ -110,7 +111,7 @@ func TestHandleBucketView(t *testing.T) {
}, },
{ {
it: "returns error if there is an S3 error", it: "returns error if there is an S3 error",
listObjectsV2Func: func(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { listObjectsFunc: func(context.Context, string, minio.ListObjectsOptions) <-chan minio.ObjectInfo {
objCh := make(chan minio.ObjectInfo) objCh := make(chan minio.ObjectInfo)
go func() { go func() {
objCh <- minio.ObjectInfo{Err: errS3} objCh <- minio.ObjectInfo{Err: errS3}
@ -131,7 +132,7 @@ func TestHandleBucketView(t *testing.T) {
is := is.New(t) is := is.New(t)
s3 := &mocks.S3Mock{ s3 := &mocks.S3Mock{
ListObjectsV2Func: tc.listObjectsV2Func, ListObjectsFunc: tc.listObjectsFunc,
} }
templates := os.DirFS(filepath.Join("..", "..", "..", "web", "template")) templates := os.DirFS(filepath.Join("..", "..", "..", "web", "template"))

View file

@ -9,8 +9,8 @@ import (
// HandleBucketsView renders all buckets on an HTML page. // HandleBucketsView renders all buckets on an HTML page.
func HandleBucketsView(s3 S3, templates fs.FS) http.HandlerFunc { func HandleBucketsView(s3 S3, templates fs.FS) http.HandlerFunc {
return func(w http.ResponseWriter, _ *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
buckets, err := s3.ListBuckets() buckets, err := s3.ListBuckets(r.Context())
if err != nil { if err != nil {
handleHTTPError(w, fmt.Errorf("error listing buckets: %w", err)) handleHTTPError(w, fmt.Errorf("error listing buckets: %w", err))
return return

View file

@ -1,6 +1,7 @@
package s3manager_test package s3manager_test
import ( import (
"context"
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -12,7 +13,7 @@ import (
"github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/mastertinner/s3manager/internal/app/s3manager"
"github.com/mastertinner/s3manager/internal/app/s3manager/mocks" "github.com/mastertinner/s3manager/internal/app/s3manager/mocks"
"github.com/matryer/is" "github.com/matryer/is"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
func TestHandleBucketsView(t *testing.T) { func TestHandleBucketsView(t *testing.T) {
@ -20,13 +21,13 @@ func TestHandleBucketsView(t *testing.T) {
cases := []struct { cases := []struct {
it string it string
listBucketsFunc func() ([]minio.BucketInfo, error) listBucketsFunc func(context.Context) ([]minio.BucketInfo, error)
expectedStatusCode int expectedStatusCode int
expectedBodyContains string expectedBodyContains string
}{ }{
{ {
it: "renders a list of buckets", it: "renders a list of buckets",
listBucketsFunc: func() ([]minio.BucketInfo, error) { listBucketsFunc: func(context.Context) ([]minio.BucketInfo, error) {
return []minio.BucketInfo{{Name: "testBucket"}}, nil return []minio.BucketInfo{{Name: "testBucket"}}, nil
}, },
expectedStatusCode: http.StatusOK, expectedStatusCode: http.StatusOK,
@ -34,7 +35,7 @@ func TestHandleBucketsView(t *testing.T) {
}, },
{ {
it: "renders placeholder if no buckets", it: "renders placeholder if no buckets",
listBucketsFunc: func() ([]minio.BucketInfo, error) { listBucketsFunc: func(context.Context) ([]minio.BucketInfo, error) {
return []minio.BucketInfo{}, nil return []minio.BucketInfo{}, nil
}, },
expectedStatusCode: http.StatusOK, expectedStatusCode: http.StatusOK,
@ -42,7 +43,7 @@ func TestHandleBucketsView(t *testing.T) {
}, },
{ {
it: "returns error if there is an S3 error", it: "returns error if there is an S3 error",
listBucketsFunc: func() ([]minio.BucketInfo, error) { listBucketsFunc: func(context.Context) ([]minio.BucketInfo, error) {
return []minio.BucketInfo{}, errS3 return []minio.BucketInfo{}, errS3
}, },
expectedStatusCode: http.StatusInternalServerError, expectedStatusCode: http.StatusInternalServerError,

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
// HandleCreateBucket creates a new bucket. // HandleCreateBucket creates a new bucket.
@ -18,7 +18,7 @@ func HandleCreateBucket(s3 S3) http.HandlerFunc {
return return
} }
err = s3.MakeBucket(bucket.Name, "") err = s3.MakeBucket(r.Context(), bucket.Name, minio.MakeBucketOptions{})
if err != nil { if err != nil {
handleHTTPError(w, fmt.Errorf("error making bucket: %w", err)) handleHTTPError(w, fmt.Errorf("error making bucket: %w", err))
return return

View file

@ -2,6 +2,7 @@ package s3manager_test
import ( import (
"bytes" "bytes"
"context"
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -11,6 +12,7 @@ import (
"github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/mastertinner/s3manager/internal/app/s3manager"
"github.com/mastertinner/s3manager/internal/app/s3manager/mocks" "github.com/mastertinner/s3manager/internal/app/s3manager/mocks"
"github.com/matryer/is" "github.com/matryer/is"
"github.com/minio/minio-go/v7"
) )
func TestHandleCreateBucket(t *testing.T) { func TestHandleCreateBucket(t *testing.T) {
@ -18,14 +20,14 @@ func TestHandleCreateBucket(t *testing.T) {
cases := []struct { cases := []struct {
it string it string
makeBucketFunc func(string, string) error makeBucketFunc func(context.Context, string, minio.MakeBucketOptions) error
body string body string
expectedStatusCode int expectedStatusCode int
expectedBodyContains string expectedBodyContains string
}{ }{
{ {
it: "creates a new bucket", it: "creates a new bucket",
makeBucketFunc: func(string, string) error { makeBucketFunc: func(context.Context, string, minio.MakeBucketOptions) error {
return nil return nil
}, },
body: `{"name":"myBucket"}`, body: `{"name":"myBucket"}`,
@ -34,7 +36,7 @@ func TestHandleCreateBucket(t *testing.T) {
}, },
{ {
it: "returns error for empty request", it: "returns error for empty request",
makeBucketFunc: func(string, string) error { makeBucketFunc: func(context.Context, string, minio.MakeBucketOptions) error {
return nil return nil
}, },
body: "", body: "",
@ -43,7 +45,7 @@ func TestHandleCreateBucket(t *testing.T) {
}, },
{ {
it: "returns error for malformed request", it: "returns error for malformed request",
makeBucketFunc: func(string, string) error { makeBucketFunc: func(context.Context, string, minio.MakeBucketOptions) error {
return nil return nil
}, },
body: "}", body: "}",
@ -52,7 +54,7 @@ func TestHandleCreateBucket(t *testing.T) {
}, },
{ {
it: "returns error if there is an S3 error", it: "returns error if there is an S3 error",
makeBucketFunc: func(string, string) error { makeBucketFunc: func(context.Context, string, minio.MakeBucketOptions) error {
return errS3 return errS3
}, },
body: `{"name":"myBucket"}`, body: `{"name":"myBucket"}`,

View file

@ -5,7 +5,7 @@ import (
"net/http" "net/http"
"github.com/matryer/way" "github.com/matryer/way"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
// HandleCreateObject uploads a new object. // HandleCreateObject uploads a new object.
@ -26,7 +26,7 @@ func HandleCreateObject(s3 S3) http.HandlerFunc {
defer file.Close() defer file.Close()
opts := minio.PutObjectOptions{ContentType: "application/octet-stream"} opts := minio.PutObjectOptions{ContentType: "application/octet-stream"}
_, err = s3.PutObject(bucketName, header.Filename, file, -1, opts) _, err = s3.PutObject(r.Context(), bucketName, header.Filename, file, -1, opts)
if err != nil { if err != nil {
handleHTTPError(w, fmt.Errorf("error putting object: %w", err)) handleHTTPError(w, fmt.Errorf("error putting object: %w", err))
return return

View file

@ -12,7 +12,7 @@ func HandleDeleteBucket(s3 S3) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
bucketName := way.Param(r.Context(), "bucketName") bucketName := way.Param(r.Context(), "bucketName")
err := s3.RemoveBucket(bucketName) err := s3.RemoveBucket(r.Context(), bucketName)
if err != nil { if err != nil {
handleHTTPError(w, fmt.Errorf("error removing bucket: %w", err)) handleHTTPError(w, fmt.Errorf("error removing bucket: %w", err))
return return

View file

@ -1,6 +1,7 @@
package s3manager_test package s3manager_test
import ( import (
"context"
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -17,13 +18,13 @@ func TestHandleDeleteBucket(t *testing.T) {
cases := []struct { cases := []struct {
it string it string
removeBucketFunc func(string) error removeBucketFunc func(context.Context, string) error
expectedStatusCode int expectedStatusCode int
expectedBodyContains string expectedBodyContains string
}{ }{
{ {
it: "deletes an existing bucket", it: "deletes an existing bucket",
removeBucketFunc: func(string) error { removeBucketFunc: func(context.Context, string) error {
return nil return nil
}, },
expectedStatusCode: http.StatusNoContent, expectedStatusCode: http.StatusNoContent,
@ -31,7 +32,7 @@ func TestHandleDeleteBucket(t *testing.T) {
}, },
{ {
it: "returns error if there is an S3 error", it: "returns error if there is an S3 error",
removeBucketFunc: func(string) error { removeBucketFunc: func(context.Context, string) error {
return errS3 return errS3
}, },
expectedStatusCode: http.StatusInternalServerError, expectedStatusCode: http.StatusInternalServerError,

View file

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/matryer/way" "github.com/matryer/way"
"github.com/minio/minio-go/v7"
) )
// HandleDeleteObject deletes an object. // HandleDeleteObject deletes an object.
@ -13,7 +14,7 @@ func HandleDeleteObject(s3 S3) http.HandlerFunc {
bucketName := way.Param(r.Context(), "bucketName") bucketName := way.Param(r.Context(), "bucketName")
objectName := way.Param(r.Context(), "objectName") objectName := way.Param(r.Context(), "objectName")
err := s3.RemoveObject(bucketName, objectName) err := s3.RemoveObject(r.Context(), bucketName, objectName, minio.RemoveObjectOptions{})
if err != nil { if err != nil {
handleHTTPError(w, fmt.Errorf("error removing object: %w", err)) handleHTTPError(w, fmt.Errorf("error removing object: %w", err))
return return

View file

@ -1,6 +1,7 @@
package s3manager_test package s3manager_test
import ( import (
"context"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"strings" "strings"
@ -9,6 +10,7 @@ import (
"github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/mastertinner/s3manager/internal/app/s3manager"
"github.com/mastertinner/s3manager/internal/app/s3manager/mocks" "github.com/mastertinner/s3manager/internal/app/s3manager/mocks"
"github.com/matryer/is" "github.com/matryer/is"
"github.com/minio/minio-go/v7"
) )
func TestHandleDeleteObject(t *testing.T) { func TestHandleDeleteObject(t *testing.T) {
@ -16,13 +18,13 @@ func TestHandleDeleteObject(t *testing.T) {
cases := []struct { cases := []struct {
it string it string
removeObjectFunc func(string, string) error removeObjectFunc func(context.Context, string, string, minio.RemoveObjectOptions) error
expectedStatusCode int expectedStatusCode int
expectedBodyContains string expectedBodyContains string
}{ }{
{ {
it: "deletes an existing object", it: "deletes an existing object",
removeObjectFunc: func(string, string) error { removeObjectFunc: func(context.Context, string, string, minio.RemoveObjectOptions) error {
return nil return nil
}, },
expectedStatusCode: http.StatusNoContent, expectedStatusCode: http.StatusNoContent,
@ -30,7 +32,7 @@ func TestHandleDeleteObject(t *testing.T) {
}, },
{ {
it: "returns error if there is an S3 error", it: "returns error if there is an S3 error",
removeObjectFunc: func(string, string) error { removeObjectFunc: func(context.Context, string, string, minio.RemoveObjectOptions) error {
return errS3 return errS3
}, },
expectedStatusCode: http.StatusInternalServerError, expectedStatusCode: http.StatusInternalServerError,

View file

@ -6,7 +6,7 @@ import (
"net/http" "net/http"
"github.com/matryer/way" "github.com/matryer/way"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
// HandleGetObject downloads an object to the client. // HandleGetObject downloads an object to the client.
@ -15,7 +15,7 @@ func HandleGetObject(s3 S3) http.HandlerFunc {
bucketName := way.Param(r.Context(), "bucketName") bucketName := way.Param(r.Context(), "bucketName")
objectName := way.Param(r.Context(), "objectName") objectName := way.Param(r.Context(), "objectName")
object, err := s3.GetObject(bucketName, objectName, minio.GetObjectOptions{}) object, err := s3.GetObject(r.Context(), bucketName, objectName, minio.GetObjectOptions{})
if err != nil { if err != nil {
handleHTTPError(w, fmt.Errorf("error getting object: %w", err)) handleHTTPError(w, fmt.Errorf("error getting object: %w", err))
return return

View file

@ -1,6 +1,7 @@
package s3manager_test package s3manager_test
import ( import (
"context"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -12,7 +13,7 @@ import (
"github.com/mastertinner/s3manager/internal/app/s3manager/mocks" "github.com/mastertinner/s3manager/internal/app/s3manager/mocks"
"github.com/matryer/is" "github.com/matryer/is"
"github.com/matryer/way" "github.com/matryer/way"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
func TestHandleGetObject(t *testing.T) { func TestHandleGetObject(t *testing.T) {
@ -20,7 +21,7 @@ func TestHandleGetObject(t *testing.T) {
cases := []struct { cases := []struct {
it string it string
getObjectFunc func(string, string, minio.GetObjectOptions) (*minio.Object, error) getObjectFunc func(context.Context, string, string, minio.GetObjectOptions) (*minio.Object, error)
bucketName string bucketName string
objectName string objectName string
expectedStatusCode int expectedStatusCode int
@ -28,7 +29,7 @@ func TestHandleGetObject(t *testing.T) {
}{ }{
{ {
it: "returns error if there is an S3 error", it: "returns error if there is an S3 error",
getObjectFunc: func(string, string, minio.GetObjectOptions) (*minio.Object, error) { getObjectFunc: func(context.Context, string, string, minio.GetObjectOptions) (*minio.Object, error) {
return nil, errS3 return nil, errS3
}, },
bucketName: "testBucket", bucketName: "testBucket",

View file

@ -4,8 +4,9 @@
package mocks package mocks
import ( import (
"context"
"github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/mastertinner/s3manager/internal/app/s3manager"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
"io" "io"
"sync" "sync"
) )
@ -20,25 +21,25 @@ var _ s3manager.S3 = &S3Mock{}
// //
// // make and configure a mocked s3manager.S3 // // make and configure a mocked s3manager.S3
// mockedS3 := &S3Mock{ // mockedS3 := &S3Mock{
// GetObjectFunc: func(bucketName string, objectName string, opts minio.GetObjectOptions) (*minio.Object, error) { // GetObjectFunc: func(ctx context.Context, bucketName string, objectName string, opts minio.GetObjectOptions) (*minio.Object, error) {
// panic("mock out the GetObject method") // panic("mock out the GetObject method")
// }, // },
// ListBucketsFunc: func() ([]minio.BucketInfo, error) { // ListBucketsFunc: func(ctx context.Context) ([]minio.BucketInfo, error) {
// panic("mock out the ListBuckets method") // panic("mock out the ListBuckets method")
// }, // },
// ListObjectsV2Func: func(bucketName string, objectPrefix string, recursive bool, doneCh <-chan struct{}) <-chan minio.ObjectInfo { // ListObjectsFunc: func(ctx context.Context, bucketName string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
// panic("mock out the ListObjectsV2 method") // panic("mock out the ListObjects method")
// }, // },
// MakeBucketFunc: func(bucketName string, location string) error { // MakeBucketFunc: func(ctx context.Context, bucketName string, opts minio.MakeBucketOptions) error {
// panic("mock out the MakeBucket method") // panic("mock out the MakeBucket method")
// }, // },
// PutObjectFunc: func(bucketName string, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (int64, error) { // PutObjectFunc: func(ctx context.Context, bucketName string, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (minio.UploadInfo, error) {
// panic("mock out the PutObject method") // panic("mock out the PutObject method")
// }, // },
// RemoveBucketFunc: func(bucketName string) error { // RemoveBucketFunc: func(ctx context.Context, bucketName string) error {
// panic("mock out the RemoveBucket method") // panic("mock out the RemoveBucket method")
// }, // },
// RemoveObjectFunc: func(bucketName string, objectName string) error { // RemoveObjectFunc: func(ctx context.Context, bucketName string, objectName string, opts minio.RemoveObjectOptions) error {
// panic("mock out the RemoveObject method") // panic("mock out the RemoveObject method")
// }, // },
// } // }
@ -49,30 +50,32 @@ var _ s3manager.S3 = &S3Mock{}
// } // }
type S3Mock struct { type S3Mock struct {
// GetObjectFunc mocks the GetObject method. // GetObjectFunc mocks the GetObject method.
GetObjectFunc func(bucketName string, objectName string, opts minio.GetObjectOptions) (*minio.Object, error) GetObjectFunc func(ctx context.Context, bucketName string, objectName string, opts minio.GetObjectOptions) (*minio.Object, error)
// ListBucketsFunc mocks the ListBuckets method. // ListBucketsFunc mocks the ListBuckets method.
ListBucketsFunc func() ([]minio.BucketInfo, error) ListBucketsFunc func(ctx context.Context) ([]minio.BucketInfo, error)
// ListObjectsV2Func mocks the ListObjectsV2 method. // ListObjectsFunc mocks the ListObjects method.
ListObjectsV2Func func(bucketName string, objectPrefix string, recursive bool, doneCh <-chan struct{}) <-chan minio.ObjectInfo ListObjectsFunc func(ctx context.Context, bucketName string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo
// MakeBucketFunc mocks the MakeBucket method. // MakeBucketFunc mocks the MakeBucket method.
MakeBucketFunc func(bucketName string, location string) error MakeBucketFunc func(ctx context.Context, bucketName string, opts minio.MakeBucketOptions) error
// PutObjectFunc mocks the PutObject method. // PutObjectFunc mocks the PutObject method.
PutObjectFunc func(bucketName string, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (int64, error) PutObjectFunc func(ctx context.Context, bucketName string, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (minio.UploadInfo, error)
// RemoveBucketFunc mocks the RemoveBucket method. // RemoveBucketFunc mocks the RemoveBucket method.
RemoveBucketFunc func(bucketName string) error RemoveBucketFunc func(ctx context.Context, bucketName string) error
// RemoveObjectFunc mocks the RemoveObject method. // RemoveObjectFunc mocks the RemoveObject method.
RemoveObjectFunc func(bucketName string, objectName string) error RemoveObjectFunc func(ctx context.Context, bucketName string, objectName string, opts minio.RemoveObjectOptions) error
// calls tracks calls to the methods. // calls tracks calls to the methods.
calls struct { calls struct {
// GetObject holds details about calls to the GetObject method. // GetObject holds details about calls to the GetObject method.
GetObject []struct { GetObject []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// BucketName is the bucketName argument value. // BucketName is the bucketName argument value.
BucketName string BucketName string
// ObjectName is the objectName argument value. // ObjectName is the objectName argument value.
@ -82,27 +85,31 @@ type S3Mock struct {
} }
// ListBuckets holds details about calls to the ListBuckets method. // ListBuckets holds details about calls to the ListBuckets method.
ListBuckets []struct { ListBuckets []struct {
// Ctx is the ctx argument value.
Ctx context.Context
} }
// ListObjectsV2 holds details about calls to the ListObjectsV2 method. // ListObjects holds details about calls to the ListObjects method.
ListObjectsV2 []struct { ListObjects []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// BucketName is the bucketName argument value. // BucketName is the bucketName argument value.
BucketName string BucketName string
// ObjectPrefix is the objectPrefix argument value. // Opts is the opts argument value.
ObjectPrefix string Opts minio.ListObjectsOptions
// Recursive is the recursive argument value.
Recursive bool
// DoneCh is the doneCh argument value.
DoneCh <-chan struct{}
} }
// MakeBucket holds details about calls to the MakeBucket method. // MakeBucket holds details about calls to the MakeBucket method.
MakeBucket []struct { MakeBucket []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// BucketName is the bucketName argument value. // BucketName is the bucketName argument value.
BucketName string BucketName string
// Location is the location argument value. // Opts is the opts argument value.
Location string Opts minio.MakeBucketOptions
} }
// PutObject holds details about calls to the PutObject method. // PutObject holds details about calls to the PutObject method.
PutObject []struct { PutObject []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// BucketName is the bucketName argument value. // BucketName is the bucketName argument value.
BucketName string BucketName string
// ObjectName is the objectName argument value. // ObjectName is the objectName argument value.
@ -116,20 +123,26 @@ type S3Mock struct {
} }
// RemoveBucket holds details about calls to the RemoveBucket method. // RemoveBucket holds details about calls to the RemoveBucket method.
RemoveBucket []struct { RemoveBucket []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// BucketName is the bucketName argument value. // BucketName is the bucketName argument value.
BucketName string BucketName string
} }
// RemoveObject holds details about calls to the RemoveObject method. // RemoveObject holds details about calls to the RemoveObject method.
RemoveObject []struct { RemoveObject []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// BucketName is the bucketName argument value. // BucketName is the bucketName argument value.
BucketName string BucketName string
// ObjectName is the objectName argument value. // ObjectName is the objectName argument value.
ObjectName string ObjectName string
// Opts is the opts argument value.
Opts minio.RemoveObjectOptions
} }
} }
lockGetObject sync.RWMutex lockGetObject sync.RWMutex
lockListBuckets sync.RWMutex lockListBuckets sync.RWMutex
lockListObjectsV2 sync.RWMutex lockListObjects sync.RWMutex
lockMakeBucket sync.RWMutex lockMakeBucket sync.RWMutex
lockPutObject sync.RWMutex lockPutObject sync.RWMutex
lockRemoveBucket sync.RWMutex lockRemoveBucket sync.RWMutex
@ -137,15 +150,17 @@ type S3Mock struct {
} }
// GetObject calls GetObjectFunc. // GetObject calls GetObjectFunc.
func (mock *S3Mock) GetObject(bucketName string, objectName string, opts minio.GetObjectOptions) (*minio.Object, error) { func (mock *S3Mock) GetObject(ctx context.Context, bucketName string, objectName string, opts minio.GetObjectOptions) (*minio.Object, error) {
if mock.GetObjectFunc == nil { if mock.GetObjectFunc == nil {
panic("S3Mock.GetObjectFunc: method is nil but S3.GetObject was just called") panic("S3Mock.GetObjectFunc: method is nil but S3.GetObject was just called")
} }
callInfo := struct { callInfo := struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Opts minio.GetObjectOptions Opts minio.GetObjectOptions
}{ }{
Ctx: ctx,
BucketName: bucketName, BucketName: bucketName,
ObjectName: objectName, ObjectName: objectName,
Opts: opts, Opts: opts,
@ -153,18 +168,20 @@ func (mock *S3Mock) GetObject(bucketName string, objectName string, opts minio.G
mock.lockGetObject.Lock() mock.lockGetObject.Lock()
mock.calls.GetObject = append(mock.calls.GetObject, callInfo) mock.calls.GetObject = append(mock.calls.GetObject, callInfo)
mock.lockGetObject.Unlock() mock.lockGetObject.Unlock()
return mock.GetObjectFunc(bucketName, objectName, opts) return mock.GetObjectFunc(ctx, bucketName, objectName, opts)
} }
// GetObjectCalls gets all the calls that were made to GetObject. // GetObjectCalls gets all the calls that were made to GetObject.
// Check the length with: // Check the length with:
// len(mockedS3.GetObjectCalls()) // len(mockedS3.GetObjectCalls())
func (mock *S3Mock) GetObjectCalls() []struct { func (mock *S3Mock) GetObjectCalls() []struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Opts minio.GetObjectOptions Opts minio.GetObjectOptions
} { } {
var calls []struct { var calls []struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Opts minio.GetObjectOptions Opts minio.GetObjectOptions
@ -176,24 +193,29 @@ func (mock *S3Mock) GetObjectCalls() []struct {
} }
// ListBuckets calls ListBucketsFunc. // ListBuckets calls ListBucketsFunc.
func (mock *S3Mock) ListBuckets() ([]minio.BucketInfo, error) { func (mock *S3Mock) ListBuckets(ctx context.Context) ([]minio.BucketInfo, error) {
if mock.ListBucketsFunc == nil { if mock.ListBucketsFunc == nil {
panic("S3Mock.ListBucketsFunc: method is nil but S3.ListBuckets was just called") panic("S3Mock.ListBucketsFunc: method is nil but S3.ListBuckets was just called")
} }
callInfo := struct { callInfo := struct {
}{} Ctx context.Context
}{
Ctx: ctx,
}
mock.lockListBuckets.Lock() mock.lockListBuckets.Lock()
mock.calls.ListBuckets = append(mock.calls.ListBuckets, callInfo) mock.calls.ListBuckets = append(mock.calls.ListBuckets, callInfo)
mock.lockListBuckets.Unlock() mock.lockListBuckets.Unlock()
return mock.ListBucketsFunc() return mock.ListBucketsFunc(ctx)
} }
// ListBucketsCalls gets all the calls that were made to ListBuckets. // ListBucketsCalls gets all the calls that were made to ListBuckets.
// Check the length with: // Check the length with:
// len(mockedS3.ListBucketsCalls()) // len(mockedS3.ListBucketsCalls())
func (mock *S3Mock) ListBucketsCalls() []struct { func (mock *S3Mock) ListBucketsCalls() []struct {
Ctx context.Context
} { } {
var calls []struct { var calls []struct {
Ctx context.Context
} }
mock.lockListBuckets.RLock() mock.lockListBuckets.RLock()
calls = mock.calls.ListBuckets calls = mock.calls.ListBuckets
@ -201,77 +223,77 @@ func (mock *S3Mock) ListBucketsCalls() []struct {
return calls return calls
} }
// ListObjectsV2 calls ListObjectsV2Func. // ListObjects calls ListObjectsFunc.
func (mock *S3Mock) ListObjectsV2(bucketName string, objectPrefix string, recursive bool, doneCh <-chan struct{}) <-chan minio.ObjectInfo { func (mock *S3Mock) ListObjects(ctx context.Context, bucketName string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
if mock.ListObjectsV2Func == nil { if mock.ListObjectsFunc == nil {
panic("S3Mock.ListObjectsV2Func: method is nil but S3.ListObjectsV2 was just called") panic("S3Mock.ListObjectsFunc: method is nil but S3.ListObjects was just called")
} }
callInfo := struct { callInfo := struct {
Ctx context.Context
BucketName string BucketName string
ObjectPrefix string Opts minio.ListObjectsOptions
Recursive bool
DoneCh <-chan struct{}
}{ }{
Ctx: ctx,
BucketName: bucketName, BucketName: bucketName,
ObjectPrefix: objectPrefix, Opts: opts,
Recursive: recursive,
DoneCh: doneCh,
} }
mock.lockListObjectsV2.Lock() mock.lockListObjects.Lock()
mock.calls.ListObjectsV2 = append(mock.calls.ListObjectsV2, callInfo) mock.calls.ListObjects = append(mock.calls.ListObjects, callInfo)
mock.lockListObjectsV2.Unlock() mock.lockListObjects.Unlock()
return mock.ListObjectsV2Func(bucketName, objectPrefix, recursive, doneCh) return mock.ListObjectsFunc(ctx, bucketName, opts)
} }
// ListObjectsV2Calls gets all the calls that were made to ListObjectsV2. // ListObjectsCalls gets all the calls that were made to ListObjects.
// Check the length with: // Check the length with:
// len(mockedS3.ListObjectsV2Calls()) // len(mockedS3.ListObjectsCalls())
func (mock *S3Mock) ListObjectsV2Calls() []struct { func (mock *S3Mock) ListObjectsCalls() []struct {
Ctx context.Context
BucketName string BucketName string
ObjectPrefix string Opts minio.ListObjectsOptions
Recursive bool
DoneCh <-chan struct{}
} { } {
var calls []struct { var calls []struct {
Ctx context.Context
BucketName string BucketName string
ObjectPrefix string Opts minio.ListObjectsOptions
Recursive bool
DoneCh <-chan struct{}
} }
mock.lockListObjectsV2.RLock() mock.lockListObjects.RLock()
calls = mock.calls.ListObjectsV2 calls = mock.calls.ListObjects
mock.lockListObjectsV2.RUnlock() mock.lockListObjects.RUnlock()
return calls return calls
} }
// MakeBucket calls MakeBucketFunc. // MakeBucket calls MakeBucketFunc.
func (mock *S3Mock) MakeBucket(bucketName string, location string) error { func (mock *S3Mock) MakeBucket(ctx context.Context, bucketName string, opts minio.MakeBucketOptions) error {
if mock.MakeBucketFunc == nil { if mock.MakeBucketFunc == nil {
panic("S3Mock.MakeBucketFunc: method is nil but S3.MakeBucket was just called") panic("S3Mock.MakeBucketFunc: method is nil but S3.MakeBucket was just called")
} }
callInfo := struct { callInfo := struct {
Ctx context.Context
BucketName string BucketName string
Location string Opts minio.MakeBucketOptions
}{ }{
Ctx: ctx,
BucketName: bucketName, BucketName: bucketName,
Location: location, Opts: opts,
} }
mock.lockMakeBucket.Lock() mock.lockMakeBucket.Lock()
mock.calls.MakeBucket = append(mock.calls.MakeBucket, callInfo) mock.calls.MakeBucket = append(mock.calls.MakeBucket, callInfo)
mock.lockMakeBucket.Unlock() mock.lockMakeBucket.Unlock()
return mock.MakeBucketFunc(bucketName, location) return mock.MakeBucketFunc(ctx, bucketName, opts)
} }
// MakeBucketCalls gets all the calls that were made to MakeBucket. // MakeBucketCalls gets all the calls that were made to MakeBucket.
// Check the length with: // Check the length with:
// len(mockedS3.MakeBucketCalls()) // len(mockedS3.MakeBucketCalls())
func (mock *S3Mock) MakeBucketCalls() []struct { func (mock *S3Mock) MakeBucketCalls() []struct {
Ctx context.Context
BucketName string BucketName string
Location string Opts minio.MakeBucketOptions
} { } {
var calls []struct { var calls []struct {
Ctx context.Context
BucketName string BucketName string
Location string Opts minio.MakeBucketOptions
} }
mock.lockMakeBucket.RLock() mock.lockMakeBucket.RLock()
calls = mock.calls.MakeBucket calls = mock.calls.MakeBucket
@ -280,17 +302,19 @@ func (mock *S3Mock) MakeBucketCalls() []struct {
} }
// PutObject calls PutObjectFunc. // PutObject calls PutObjectFunc.
func (mock *S3Mock) PutObject(bucketName string, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (int64, error) { func (mock *S3Mock) PutObject(ctx context.Context, bucketName string, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (minio.UploadInfo, error) {
if mock.PutObjectFunc == nil { if mock.PutObjectFunc == nil {
panic("S3Mock.PutObjectFunc: method is nil but S3.PutObject was just called") panic("S3Mock.PutObjectFunc: method is nil but S3.PutObject was just called")
} }
callInfo := struct { callInfo := struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Reader io.Reader Reader io.Reader
ObjectSize int64 ObjectSize int64
Opts minio.PutObjectOptions Opts minio.PutObjectOptions
}{ }{
Ctx: ctx,
BucketName: bucketName, BucketName: bucketName,
ObjectName: objectName, ObjectName: objectName,
Reader: reader, Reader: reader,
@ -300,13 +324,14 @@ func (mock *S3Mock) PutObject(bucketName string, objectName string, reader io.Re
mock.lockPutObject.Lock() mock.lockPutObject.Lock()
mock.calls.PutObject = append(mock.calls.PutObject, callInfo) mock.calls.PutObject = append(mock.calls.PutObject, callInfo)
mock.lockPutObject.Unlock() mock.lockPutObject.Unlock()
return mock.PutObjectFunc(bucketName, objectName, reader, objectSize, opts) return mock.PutObjectFunc(ctx, bucketName, objectName, reader, objectSize, opts)
} }
// PutObjectCalls gets all the calls that were made to PutObject. // PutObjectCalls gets all the calls that were made to PutObject.
// Check the length with: // Check the length with:
// len(mockedS3.PutObjectCalls()) // len(mockedS3.PutObjectCalls())
func (mock *S3Mock) PutObjectCalls() []struct { func (mock *S3Mock) PutObjectCalls() []struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Reader io.Reader Reader io.Reader
@ -314,6 +339,7 @@ func (mock *S3Mock) PutObjectCalls() []struct {
Opts minio.PutObjectOptions Opts minio.PutObjectOptions
} { } {
var calls []struct { var calls []struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Reader io.Reader Reader io.Reader
@ -327,28 +353,32 @@ func (mock *S3Mock) PutObjectCalls() []struct {
} }
// RemoveBucket calls RemoveBucketFunc. // RemoveBucket calls RemoveBucketFunc.
func (mock *S3Mock) RemoveBucket(bucketName string) error { func (mock *S3Mock) RemoveBucket(ctx context.Context, bucketName string) error {
if mock.RemoveBucketFunc == nil { if mock.RemoveBucketFunc == nil {
panic("S3Mock.RemoveBucketFunc: method is nil but S3.RemoveBucket was just called") panic("S3Mock.RemoveBucketFunc: method is nil but S3.RemoveBucket was just called")
} }
callInfo := struct { callInfo := struct {
Ctx context.Context
BucketName string BucketName string
}{ }{
Ctx: ctx,
BucketName: bucketName, BucketName: bucketName,
} }
mock.lockRemoveBucket.Lock() mock.lockRemoveBucket.Lock()
mock.calls.RemoveBucket = append(mock.calls.RemoveBucket, callInfo) mock.calls.RemoveBucket = append(mock.calls.RemoveBucket, callInfo)
mock.lockRemoveBucket.Unlock() mock.lockRemoveBucket.Unlock()
return mock.RemoveBucketFunc(bucketName) return mock.RemoveBucketFunc(ctx, bucketName)
} }
// RemoveBucketCalls gets all the calls that were made to RemoveBucket. // RemoveBucketCalls gets all the calls that were made to RemoveBucket.
// Check the length with: // Check the length with:
// len(mockedS3.RemoveBucketCalls()) // len(mockedS3.RemoveBucketCalls())
func (mock *S3Mock) RemoveBucketCalls() []struct { func (mock *S3Mock) RemoveBucketCalls() []struct {
Ctx context.Context
BucketName string BucketName string
} { } {
var calls []struct { var calls []struct {
Ctx context.Context
BucketName string BucketName string
} }
mock.lockRemoveBucket.RLock() mock.lockRemoveBucket.RLock()
@ -358,33 +388,41 @@ func (mock *S3Mock) RemoveBucketCalls() []struct {
} }
// RemoveObject calls RemoveObjectFunc. // RemoveObject calls RemoveObjectFunc.
func (mock *S3Mock) RemoveObject(bucketName string, objectName string) error { func (mock *S3Mock) RemoveObject(ctx context.Context, bucketName string, objectName string, opts minio.RemoveObjectOptions) error {
if mock.RemoveObjectFunc == nil { if mock.RemoveObjectFunc == nil {
panic("S3Mock.RemoveObjectFunc: method is nil but S3.RemoveObject was just called") panic("S3Mock.RemoveObjectFunc: method is nil but S3.RemoveObject was just called")
} }
callInfo := struct { callInfo := struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Opts minio.RemoveObjectOptions
}{ }{
Ctx: ctx,
BucketName: bucketName, BucketName: bucketName,
ObjectName: objectName, ObjectName: objectName,
Opts: opts,
} }
mock.lockRemoveObject.Lock() mock.lockRemoveObject.Lock()
mock.calls.RemoveObject = append(mock.calls.RemoveObject, callInfo) mock.calls.RemoveObject = append(mock.calls.RemoveObject, callInfo)
mock.lockRemoveObject.Unlock() mock.lockRemoveObject.Unlock()
return mock.RemoveObjectFunc(bucketName, objectName) return mock.RemoveObjectFunc(ctx, bucketName, objectName, opts)
} }
// RemoveObjectCalls gets all the calls that were made to RemoveObject. // RemoveObjectCalls gets all the calls that were made to RemoveObject.
// Check the length with: // Check the length with:
// len(mockedS3.RemoveObjectCalls()) // len(mockedS3.RemoveObjectCalls())
func (mock *S3Mock) RemoveObjectCalls() []struct { func (mock *S3Mock) RemoveObjectCalls() []struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Opts minio.RemoveObjectOptions
} { } {
var calls []struct { var calls []struct {
Ctx context.Context
BucketName string BucketName string
ObjectName string ObjectName string
Opts minio.RemoveObjectOptions
} }
mock.lockRemoveObject.RLock() mock.lockRemoveObject.RLock()
calls = mock.calls.RemoveObject calls = mock.calls.RemoveObject

View file

@ -1,20 +1,21 @@
package s3manager package s3manager
import ( import (
"context"
"io" "io"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
) )
//go:generate moq -out mocks/s3.go -pkg mocks . S3 //go:generate moq -out mocks/s3.go -pkg mocks . S3
// S3 is a client to interact with S3 storage. // S3 is a client to interact with S3 storage.
type S3 interface { type S3 interface {
GetObject(bucketName, objectName string, opts minio.GetObjectOptions) (*minio.Object, error) GetObject(ctx context.Context, bucketName, objectName string, opts minio.GetObjectOptions) (*minio.Object, error)
ListBuckets() ([]minio.BucketInfo, error) ListBuckets(ctx context.Context) ([]minio.BucketInfo, error)
ListObjectsV2(bucketName, objectPrefix string, recursive bool, doneCh <-chan struct{}) <-chan minio.ObjectInfo ListObjects(ctx context.Context, bucketName string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo
MakeBucket(bucketName, location string) error MakeBucket(ctx context.Context, bucketName string, opts minio.MakeBucketOptions) error
PutObject(bucketName, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (int64, error) PutObject(ctx context.Context, bucketName, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (minio.UploadInfo, error)
RemoveBucket(bucketName string) error RemoveBucket(ctx context.Context, bucketName string) error
RemoveObject(bucketName, objectName string) error RemoveObject(ctx context.Context, bucketName, objectName string, opts minio.RemoveObjectOptions) error
} }

19
main.go
View file

@ -13,7 +13,8 @@ import (
"github.com/mastertinner/adapters/logging" "github.com/mastertinner/adapters/logging"
"github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/mastertinner/s3manager/internal/app/s3manager"
"github.com/matryer/way" "github.com/matryer/way"
minio "github.com/minio/minio-go" "github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
) )
//go:embed web/template //go:embed web/template
@ -32,6 +33,7 @@ func main() {
if !ok { if !ok {
log.Fatal("please provide SECRET_ACCESS_KEY") log.Fatal("please provide SECRET_ACCESS_KEY")
} }
region := os.Getenv("REGION")
useSSL := getBoolEnvWithDefault("USE_SSL", true) useSSL := getBoolEnvWithDefault("USE_SSL", true)
skipSSLVerification := getBoolEnvWithDefault("SKIP_SSL_VERIFICATION", false) skipSSLVerification := getBoolEnvWithDefault("SKIP_SSL_VERIFICATION", false)
port, ok := os.LookupEnv("PORT") port, ok := os.LookupEnv("PORT")
@ -46,12 +48,19 @@ func main() {
} }
// Set up S3 client // Set up S3 client
s3, err := minio.New(endpoint, accessKeyID, secretAccessKey, useSSL) opts := &minio.Options{
if err != nil { Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
log.Fatalln(fmt.Errorf("error creating s3 client: %w", err)) Secure: useSSL,
}
if region != "" {
opts.Region = region
} }
if useSSL && skipSSLVerification { if useSSL && skipSSLVerification {
s3.SetCustomTransport(&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}) //nolint:gosec opts.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} //nolint:gosec
}
s3, err := minio.New(endpoint, opts)
if err != nil {
log.Fatalln(fmt.Errorf("error creating s3 client: %w", err))
} }
// Set up router // Set up router