summaryrefslogtreecommitdiff
path: root/workhorse
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-20 11:10:13 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-20 11:10:13 +0000
commit0ea3fcec397b69815975647f5e2aa5fe944a8486 (patch)
tree7979381b89d26011bcf9bdc989a40fcc2f1ed4ff /workhorse
parent72123183a20411a36d607d70b12d57c484394c8e (diff)
downloadgitlab-ce-0ea3fcec397b69815975647f5e2aa5fe944a8486.tar.gz
Add latest changes from gitlab-org/gitlab@15-1-stable-eev15.1.0-rc42
Diffstat (limited to 'workhorse')
-rw-r--r--workhorse/cmd/gitlab-resize-image/png/reader.go3
-rw-r--r--workhorse/cmd/gitlab-resize-image/png/reader_test.go5
-rw-r--r--workhorse/config_test.go84
-rw-r--r--workhorse/gitaly_test.go3
-rw-r--r--workhorse/go.mod98
-rw-r--r--workhorse/go.sum293
-rw-r--r--workhorse/internal/api/api.go46
-rw-r--r--workhorse/internal/api/block_test.go4
-rw-r--r--workhorse/internal/artifacts/entry_test.go14
-rw-r--r--workhorse/internal/badgateway/roundtripper.go4
-rw-r--r--workhorse/internal/badgateway/roundtripper_test.go4
-rw-r--r--workhorse/internal/config/config.go1
-rw-r--r--workhorse/internal/git/archive.go3
-rw-r--r--workhorse/internal/git/archive_test.go4
-rw-r--r--workhorse/internal/git/upload-pack_test.go8
-rw-r--r--workhorse/internal/helper/helpers.go6
-rw-r--r--workhorse/internal/helper/tempfile.go3
-rw-r--r--workhorse/internal/helper/writeafterreader.go3
-rw-r--r--workhorse/internal/helper/writeafterreader_test.go7
-rw-r--r--workhorse/internal/httprs/httprs.go3
-rw-r--r--workhorse/internal/httprs/httprs_test.go11
-rw-r--r--workhorse/internal/imageresizer/image_resizer_test.go10
-rw-r--r--workhorse/internal/lsif_transformer/parser/cache.go5
-rw-r--r--workhorse/internal/lsif_transformer/parser/cache_test.go6
-rw-r--r--workhorse/internal/lsif_transformer/parser/docs.go4
-rw-r--r--workhorse/internal/lsif_transformer/parser/docs_test.go6
-rw-r--r--workhorse/internal/lsif_transformer/parser/hovers.go9
-rw-r--r--workhorse/internal/lsif_transformer/parser/hovers_test.go2
-rw-r--r--workhorse/internal/lsif_transformer/parser/parser.go11
-rw-r--r--workhorse/internal/lsif_transformer/parser/parser_test.go7
-rw-r--r--workhorse/internal/lsif_transformer/parser/performance_test.go5
-rw-r--r--workhorse/internal/lsif_transformer/parser/ranges.go8
-rw-r--r--workhorse/internal/lsif_transformer/parser/ranges_test.go2
-rw-r--r--workhorse/internal/lsif_transformer/parser/references.go8
-rw-r--r--workhorse/internal/lsif_transformer/parser/references_test.go4
-rw-r--r--workhorse/internal/secret/jwt.go2
-rw-r--r--workhorse/internal/secret/secret.go4
-rw-r--r--workhorse/internal/senddata/contentprocessor/contentprocessor_test.go3
-rw-r--r--workhorse/internal/senddata/writer_test.go3
-rw-r--r--workhorse/internal/sendfile/sendfile.go3
-rw-r--r--workhorse/internal/sendfile/sendfile_test.go15
-rw-r--r--workhorse/internal/sendurl/sendurl_test.go3
-rw-r--r--workhorse/internal/staticpages/deploy_page.go4
-rw-r--r--workhorse/internal/staticpages/deploy_page_test.go15
-rw-r--r--workhorse/internal/staticpages/error_pages.go4
-rw-r--r--workhorse/internal/staticpages/error_pages_test.go39
-rw-r--r--workhorse/internal/staticpages/servefile_test.go25
-rw-r--r--workhorse/internal/testhelper/gitaly.go6
-rw-r--r--workhorse/internal/testhelper/testhelper.go9
-rw-r--r--workhorse/internal/upload/artifacts_store_test.go25
-rw-r--r--workhorse/internal/upload/artifacts_upload_test.go17
-rw-r--r--workhorse/internal/upload/artifacts_uploader.go67
-rw-r--r--workhorse/internal/upload/body_uploader.go6
-rw-r--r--workhorse/internal/upload/body_uploader_test.go5
-rw-r--r--workhorse/internal/upload/destination/destination.go25
-rw-r--r--workhorse/internal/upload/destination/destination_test.go54
-rw-r--r--workhorse/internal/upload/destination/filestore/filestore_test.go5
-rw-r--r--workhorse/internal/upload/destination/objectstore/gocloud_object_test.go3
-rw-r--r--workhorse/internal/upload/destination/objectstore/multipart.go9
-rw-r--r--workhorse/internal/upload/destination/objectstore/multipart_test.go4
-rw-r--r--workhorse/internal/upload/destination/objectstore/object.go3
-rw-r--r--workhorse/internal/upload/destination/objectstore/s3_object_test.go18
-rw-r--r--workhorse/internal/upload/destination/objectstore/s3_session.go7
-rw-r--r--workhorse/internal/upload/destination/objectstore/test/gocloud_stub.go12
-rw-r--r--workhorse/internal/upload/destination/objectstore/test/objectstore_stub.go24
-rw-r--r--workhorse/internal/upload/destination/objectstore/test/s3_stub.go10
-rw-r--r--workhorse/internal/upload/destination/reader_test.go4
-rw-r--r--workhorse/internal/upload/destination/upload_opts.go2
-rw-r--r--workhorse/internal/upload/destination/upload_opts_test.go3
-rw-r--r--workhorse/internal/upload/exif.go91
-rw-r--r--workhorse/internal/upload/exif/exif_test.go7
-rw-r--r--workhorse/internal/upload/multipart_uploader.go29
-rw-r--r--workhorse/internal/upload/rewrite.go169
-rw-r--r--workhorse/internal/upload/saved_file_tracker.go14
-rw-r--r--workhorse/internal/upload/skip_rails_authorizer.go22
-rw-r--r--workhorse/internal/upload/uploads.go11
-rw-r--r--workhorse/internal/upload/uploads_test.go146
-rw-r--r--workhorse/internal/upstream/handlers_test.go6
-rw-r--r--workhorse/internal/upstream/roundtripper/roundtripper_test.go4
-rw-r--r--workhorse/internal/upstream/routes.go2
-rw-r--r--workhorse/internal/upstream/upstream_test.go3
-rw-r--r--workhorse/internal/utils/svg/README.md4
-rw-r--r--workhorse/internal/zipartifacts/metadata_test.go7
-rw-r--r--workhorse/logging.go5
-rw-r--r--workhorse/main.go18
-rw-r--r--workhorse/main_test.go11
-rw-r--r--workhorse/proxy_test.go4
-rw-r--r--workhorse/sendfile_test.go8
-rw-r--r--workhorse/upload_test.go28
89 files changed, 969 insertions, 752 deletions
diff --git a/workhorse/cmd/gitlab-resize-image/png/reader.go b/workhorse/cmd/gitlab-resize-image/png/reader.go
index 8229454ee3b..c2c6a0899c2 100644
--- a/workhorse/cmd/gitlab-resize-image/png/reader.go
+++ b/workhorse/cmd/gitlab-resize-image/png/reader.go
@@ -5,7 +5,6 @@ import (
"encoding/binary"
"fmt"
"io"
- "io/ioutil"
"os"
)
@@ -53,7 +52,7 @@ func (r *Reader) Read(p []byte) (int, error) {
chunkLen := int64(binary.BigEndian.Uint32(header[:4]))
if chunkType := string(header[4:]); chunkType == "iCCP" {
debug("!! iCCP chunk found; skipping")
- if _, err := io.CopyN(ioutil.Discard, r.underlying, chunkLen+crcLen); err != nil {
+ if _, err := io.CopyN(io.Discard, r.underlying, chunkLen+crcLen); err != nil {
return 0, err
}
continue
diff --git a/workhorse/cmd/gitlab-resize-image/png/reader_test.go b/workhorse/cmd/gitlab-resize-image/png/reader_test.go
index 2b2d5df24e9..69dacbc865e 100644
--- a/workhorse/cmd/gitlab-resize-image/png/reader_test.go
+++ b/workhorse/cmd/gitlab-resize-image/png/reader_test.go
@@ -5,7 +5,6 @@ import (
"hash/crc64"
"image"
"io"
- "io/ioutil"
"os"
"testing"
@@ -85,9 +84,9 @@ func requireValidImage(t *testing.T, r io.Reader, expected string) {
}
func requireStreamUnchanged(t *testing.T, actual io.Reader, expected io.Reader) {
- actualBytes, err := ioutil.ReadAll(actual)
+ actualBytes, err := io.ReadAll(actual)
require.NoError(t, err)
- expectedBytes, err := ioutil.ReadAll(expected)
+ expectedBytes, err := io.ReadAll(expected)
require.NoError(t, err)
table := crc64.MakeTable(crc64.ISO)
diff --git a/workhorse/config_test.go b/workhorse/config_test.go
index 0c0072322ac..a6a1bdd7187 100644
--- a/workhorse/config_test.go
+++ b/workhorse/config_test.go
@@ -3,7 +3,6 @@ package main
import (
"flag"
"io"
- "io/ioutil"
"net/url"
"os"
"testing"
@@ -24,7 +23,7 @@ func TestDefaultConfig(t *testing.T) {
}
func TestConfigFile(t *testing.T) {
- f, err := ioutil.TempFile("", "workhorse-config-test")
+ f, err := os.CreateTemp("", "workhorse-config-test")
require.NoError(t, err)
defer os.Remove(f.Name())
@@ -47,6 +46,15 @@ certificate = "/path/to/certificate"
key = "/path/to/private/key"
min_version = "tls1.1"
max_version = "tls1.2"
+[[listeners]]
+network = "tcp"
+addr = "localhost:3444"
+[metrics_listener]
+network = "tcp"
+addr = "localhost:3445"
+[metrics_listener.tls]
+certificate = "/path/to/certificate"
+key = "/path/to/private/key"
`
_, err = io.WriteString(f, data)
require.NoError(t, err)
@@ -66,14 +74,69 @@ max_version = "tls1.2"
require.Equal(t, []string{"10.0.0.1/8"}, cfg.TrustedCIDRsForPropagation)
require.Equal(t, 60*time.Second, cfg.ShutdownTimeout.Duration)
- require.Len(t, cfg.Listeners, 1)
- listener := cfg.Listeners[0]
- require.Equal(t, "/path/to/certificate", listener.Tls.Certificate)
- require.Equal(t, "/path/to/private/key", listener.Tls.Key)
- require.Equal(t, "tls1.1", listener.Tls.MinVersion)
- require.Equal(t, "tls1.2", listener.Tls.MaxVersion)
- require.Equal(t, "tcp", listener.Network)
- require.Equal(t, "localhost:3443", listener.Addr)
+ listenerConfigs := []config.ListenerConfig{
+ {
+ Network: "tcp",
+ Addr: "localhost:3445",
+ Tls: &config.TlsConfig{
+ Certificate: "/path/to/certificate",
+ Key: "/path/to/private/key",
+ },
+ },
+ {
+ Network: "tcp",
+ Addr: "localhost:3443",
+ Tls: &config.TlsConfig{
+ Certificate: "/path/to/certificate",
+ Key: "/path/to/private/key",
+ MinVersion: "tls1.1",
+ MaxVersion: "tls1.2",
+ },
+ },
+ {
+ Network: "tcp",
+ Addr: "localhost:3444",
+ },
+ }
+
+ require.Len(t, cfg.Listeners, 2)
+ require.NotNil(t, cfg.MetricsListener)
+
+ for i, cfg := range []config.ListenerConfig{*cfg.MetricsListener, cfg.Listeners[0], cfg.Listeners[1]} {
+ require.Equal(t, listenerConfigs[i].Network, cfg.Network)
+ require.Equal(t, listenerConfigs[i].Addr, cfg.Addr)
+ }
+
+ for i, cfg := range []config.ListenerConfig{*cfg.MetricsListener, cfg.Listeners[0]} {
+ require.Equal(t, listenerConfigs[i].Tls.Certificate, cfg.Tls.Certificate)
+ require.Equal(t, listenerConfigs[i].Tls.Key, cfg.Tls.Key)
+ require.Equal(t, listenerConfigs[i].Tls.MinVersion, cfg.Tls.MinVersion)
+ require.Equal(t, listenerConfigs[i].Tls.MaxVersion, cfg.Tls.MaxVersion)
+ }
+
+ require.Nil(t, cfg.Listeners[1].Tls)
+}
+
+func TestTwoMetricsAddrsAreSpecifiedError(t *testing.T) {
+ f, err := os.CreateTemp("", "workhorse-config-test")
+ require.NoError(t, err)
+ defer os.Remove(f.Name())
+
+ data := `
+[metrics_listener]
+network = "tcp"
+addr = "localhost:3445"
+`
+ _, err = io.WriteString(f, data)
+ require.NoError(t, err)
+ require.NoError(t, f.Close())
+
+ args := []string{
+ "-config", f.Name(),
+ "-prometheusListenAddr", "prometheus listen addr",
+ }
+ _, _, err = buildConfig("test", args)
+ require.EqualError(t, err, "configFile: both prometheusListenAddr and metrics_listener can't be specified")
}
func TestConfigErrorHelp(t *testing.T) {
@@ -215,6 +278,7 @@ func TestConfigFlagParsing(t *testing.T) {
APICILongPollingDuration: 234 * time.Second,
PropagateCorrelationID: true,
ImageResizerConfig: config.DefaultImageResizerConfig,
+ MetricsListener: &config.ListenerConfig{Network: "tcp", Addr: "prometheus listen addr"},
}
require.Equal(t, expectedCfg, cfg)
}
diff --git a/workhorse/gitaly_test.go b/workhorse/gitaly_test.go
index 38e807f45cc..838e5ecb2fd 100644
--- a/workhorse/gitaly_test.go
+++ b/workhorse/gitaly_test.go
@@ -5,7 +5,6 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
- "io/ioutil"
"math/rand"
"net"
"net/http"
@@ -651,7 +650,7 @@ func TestGetArchiveProxiedToGitalySuccessfully(t *testing.T) {
_, err := os.Stat(tc.archivePath)
require.True(t, os.IsNotExist(err), "expected 'does not exist', got: %v", err)
} else {
- cachedArchive, err := ioutil.ReadFile(tc.archivePath)
+ cachedArchive, err := os.ReadFile(tc.archivePath)
require.NoError(t, err)
require.Equal(t, expectedBody, string(cachedArchive))
}
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 01dc6e468bc..0e102180cb6 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -1,16 +1,16 @@
module gitlab.com/gitlab-org/gitlab/workhorse
-go 1.16
+go 1.17
require (
- github.com/Azure/azure-storage-blob-go v0.13.0
+ github.com/Azure/azure-storage-blob-go v0.14.0
github.com/BurntSushi/toml v0.3.1
github.com/FZambia/sentinel v1.0.0
- github.com/alecthomas/chroma v0.7.3
- github.com/aws/aws-sdk-go v1.38.35
+ github.com/alecthomas/chroma v0.10.0
+ github.com/aws/aws-sdk-go v1.43.31
github.com/disintegration/imaging v1.6.2
github.com/getsentry/raven-go v0.2.0
- github.com/golang-jwt/jwt/v4 v4.0.0
+ github.com/golang-jwt/jwt/v4 v4.4.1
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721
github.com/golang/protobuf v1.5.2
github.com/gomodule/redigo v2.0.0+incompatible
@@ -23,19 +23,95 @@ require (
github.com/prometheus/client_golang v1.12.1
github.com/rafaeljusto/redigomock v0.0.0-20190202135759-257e089e14a1
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a
- github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/goconvey v1.6.4
github.com/stretchr/testify v1.7.0
gitlab.com/gitlab-org/gitaly/v14 v14.10.0-rc1.0.20220426135705-ccfab390f7c3
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
- gitlab.com/gitlab-org/labkit v1.14.0
- gocloud.dev v0.23.0
+ gitlab.com/gitlab-org/labkit v1.15.0
+ gocloud.dev v0.25.0
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
- golang.org/x/net v0.0.0-20211008194852-3b03d305991f
+ golang.org/x/net v0.0.0-20220401154927-543a649e0bdd
golang.org/x/tools v0.1.5
- google.golang.org/grpc v1.40.0
- google.golang.org/protobuf v1.27.1
+ google.golang.org/grpc v1.45.0
+ google.golang.org/protobuf v1.28.0
honnef.co/go/tools v0.1.3
)
+
+require (
+ cloud.google.com/go v0.100.2 // indirect
+ cloud.google.com/go/compute v1.5.0 // indirect
+ cloud.google.com/go/monitoring v1.4.0 // indirect
+ cloud.google.com/go/profiler v0.1.0 // indirect
+ cloud.google.com/go/trace v1.2.0 // indirect
+ contrib.go.opencensus.io/exporter/stackdriver v0.13.10 // indirect
+ github.com/Azure/azure-pipeline-go v0.2.3 // indirect
+ github.com/Azure/go-autorest v14.2.0+incompatible // indirect
+ github.com/Azure/go-autorest/autorest v0.11.22 // indirect
+ github.com/Azure/go-autorest/autorest/adal v0.9.17 // indirect
+ github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
+ github.com/Azure/go-autorest/logger v0.2.1 // indirect
+ github.com/Azure/go-autorest/tracing v0.6.0 // indirect
+ github.com/DataDog/datadog-go v4.4.0+incompatible // indirect
+ github.com/DataDog/sketches-go v1.0.0 // indirect
+ github.com/Microsoft/go-winio v0.5.0 // indirect
+ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
+ github.com/beevik/ntp v0.3.0 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
+ github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
+ github.com/client9/reopen v1.0.0 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/dlclark/regexp2 v1.4.0 // indirect
+ github.com/go-ole/go-ole v1.2.4 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/google/go-cmp v0.5.7 // indirect
+ github.com/google/pprof v0.0.0-20210804190019-f964ff605595 // indirect
+ github.com/google/uuid v1.3.0 // indirect
+ github.com/google/wire v0.5.0 // indirect
+ github.com/googleapis/gax-go/v2 v2.2.0 // indirect
+ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
+ github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864 // indirect
+ github.com/jmespath/go-jmespath v0.4.0 // indirect
+ github.com/jtolds/gls v4.20.0+incompatible // indirect
+ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20210210170715-a8dfcb80d3a7 // indirect
+ github.com/lightstep/lightstep-tracer-go v0.25.0 // indirect
+ github.com/mattn/go-ieproxy v0.0.6 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
+ github.com/mitchellh/reflectwalk v1.0.0 // indirect
+ github.com/oklog/ulid/v2 v2.0.2 // indirect
+ github.com/opentracing/opentracing-go v1.2.0 // indirect
+ github.com/philhofer/fwd v1.1.1 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/prometheus/client_model v0.2.0 // indirect
+ github.com/prometheus/common v0.32.1 // indirect
+ github.com/prometheus/procfs v0.7.3 // indirect
+ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 // indirect
+ github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500 // indirect
+ github.com/shirou/gopsutil/v3 v3.21.2 // indirect
+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
+ github.com/tinylib/msgp v1.1.2 // indirect
+ github.com/tklauser/go-sysconf v0.3.4 // indirect
+ github.com/tklauser/numcpus v0.2.1 // indirect
+ github.com/uber/jaeger-client-go v2.29.1+incompatible // indirect
+ github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
+ go.opencensus.io v0.23.0 // indirect
+ go.uber.org/atomic v1.9.0 // indirect
+ golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
+ golang.org/x/mod v0.5.0 // indirect
+ golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
+ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
+ golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f // indirect
+ golang.org/x/text v0.3.7 // indirect
+ golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
+ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
+ google.golang.org/api v0.74.0 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de // indirect
+ gopkg.in/DataDog/dd-trace-go.v1 v1.32.0 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
+)
diff --git a/workhorse/go.sum b/workhorse/go.sum
index ed959f44889..61f11579d18 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -22,21 +22,43 @@ cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPT
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
+cloud.google.com/go v0.82.0/go.mod h1:vlKccHJGuFBFufnAnuB08dfEH9Y3H7dzDzRECFdC2TA=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
-cloud.google.com/go v0.92.2 h1:podK44+0gcW5rWGMjJiPH0+rzkCTQx/zT0qF5CLqVkM=
cloud.google.com/go v0.92.2/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
+cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
+cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
+cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
+cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
+cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
+cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
+cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
+cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw=
+cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
+cloud.google.com/go/compute v1.5.0 h1:b1zWmYuuHz7gO9kDcM/EpHGr06UgsYNRpNJzI2kFiLM=
+cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.5.0/go.mod h1:c4nNYR1qdq7eaZ+jSc5fonrQN2k3M7sWATcYTiakjEo=
+cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
+cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c=
+cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw=
+cloud.google.com/go/iam v0.3.0 h1:exkAomrVUuzx9kWFI1wm3KI0uoDeUFPB4kKGzx6x+Gc=
+cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
+cloud.google.com/go/kms v1.1.0/go.mod h1:WdbppnCDMDpOvoYBMn1+gNmOeEoZYqAv+HeuKARGCXI=
+cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA=
+cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4=
+cloud.google.com/go/monitoring v1.4.0 h1:05+IuNMbh40hbxcqQ4SnynbwZbLG1Wc9dysIJxnfv7U=
+cloud.google.com/go/monitoring v1.4.0/go.mod h1:y6xnxfwI3hTFWOdkOaD7nfJVlwuC3/mS/5kvtT131p4=
cloud.google.com/go/profiler v0.1.0 h1:MG/rxKC1MztRfEWMGYKFISxyZak5hNh29f0A/z2tvWk=
cloud.google.com/go/profiler v0.1.0/go.mod h1:D7S7LV/zKbRWkOzYL1b5xytpqt8Ikd/v/yvf1/Tx2pQ=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@@ -44,47 +66,68 @@ cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/pubsub v1.10.3/go.mod h1:FUcc28GpGxxACoklPsE1sCtbkY4Ix+ro7yvw+h82Jn4=
+cloud.google.com/go/pubsub v1.19.0/go.mod h1:/O9kmSe9bb9KRnIAWkzmqhPjHo6LtzGOBYd/kr06XSs=
+cloud.google.com/go/secretmanager v1.3.0/go.mod h1:+oLTkouyiYiabAQNugCeTS3PAArGiMJuBqvJnJsyH+U=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-cloud.google.com/go/storage v1.15.0 h1:Ljj+ZXVEhCr/1+4ZhvtteN1ND7UUsNTlduGclLh8GO0=
cloud.google.com/go/storage v1.15.0/go.mod h1:mjjQMoxxyGH7Jr8K5qrx6N2O0AHsczI61sMNn03GIZI=
-cloud.google.com/go/trace v0.1.0 h1:nUGUK79FOkN0UGUXhBmVBkbu1PYsHe0YyFSPLOD9Npg=
+cloud.google.com/go/storage v1.21.0 h1:HwnT2u2D309SFDHQII6m18HlrCi3jAXhUMTLOWXYH14=
+cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKuqnZI01LAA=
cloud.google.com/go/trace v0.1.0/go.mod h1:wxEwsoeRVPbeSkt7ZC9nWCgmoKQRAoySN7XHW2AmI7g=
+cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A=
+cloud.google.com/go/trace v1.2.0 h1:oIaB4KahkIUOpLSAAjEJ8y2desbjY/x/RfP4O3KAtTI=
+cloud.google.com/go/trace v1.2.0/go.mod h1:Wc8y/uYyOhPy12KEnXG9XGrvfMz5F5SrYecQlbW1rwM=
contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
-contrib.go.opencensus.io/exporter/stackdriver v0.13.8 h1:lIFYmQsqejvlq+GobFUbC5F0prD5gvhP6r0gWLZRDq4=
contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ=
+contrib.go.opencensus.io/exporter/stackdriver v0.13.10 h1:a9+GZPUe+ONKUwULjlEOucMMG0qfSCCenlji0Nhqbys=
+contrib.go.opencensus.io/exporter/stackdriver v0.13.10/go.mod h1:I5htMbyta491eUxufwwZPQdcKvvgzMB4O9ni41YnIM8=
contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-amqp-common-go/v3 v3.1.0/go.mod h1:PBIGdzcO1teYoufTKMcGibdKaYZv4avS+O6LNIp8bq0=
+github.com/Azure/azure-amqp-common-go/v3 v3.2.1/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
+github.com/Azure/azure-amqp-common-go/v3 v3.2.2/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v54.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-sdk-for-go v59.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
+github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
github.com/Azure/azure-service-bus-go v0.10.11/go.mod h1:AWw9eTTWZVZyvgpPahD1ybz3a8/vT3GsJDS8KYex55U=
-github.com/Azure/azure-storage-blob-go v0.13.0 h1:lgWHvFh+UYBNVQLFHXkvul2f6yOPA9PIH82RTG2cSwc=
+github.com/Azure/azure-service-bus-go v0.11.5/go.mod h1:MI6ge2CuQWBVq+ly456MY7XqNLJip5LO1iSFodbNLbU=
github.com/Azure/azure-storage-blob-go v0.13.0/go.mod h1:pA9kNqtjUeQF2zOSu4s//nUdBD+e64lEuc4sVnuOfNs=
+github.com/Azure/azure-storage-blob-go v0.14.0 h1:1BCg74AmVdYwO3dlKwtFU1V0wU2PZdREkXvAmZJRUlM=
+github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck=
github.com/Azure/go-amqp v0.13.0/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs=
github.com/Azure/go-amqp v0.13.4/go.mod h1:wbpCKA8tR5MLgRyIu+bb+S6ECdIDdYJ0NlpFE9xsBPI=
github.com/Azure/go-amqp v0.13.7/go.mod h1:wbpCKA8tR5MLgRyIu+bb+S6ECdIDdYJ0NlpFE9xsBPI=
+github.com/Azure/go-amqp v0.16.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg=
+github.com/Azure/go-amqp v0.16.4/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
-github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
+github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
+github.com/Azure/go-autorest/autorest v0.11.22 h1:bXiQwDjrRmBQOE67bwlvUKAC1EU1yZTPQ38c+bstZws=
+github.com/Azure/go-autorest/autorest v0.11.22/go.mod h1:BAWYUWGPEtKPzjVkp0Q6an0MJcJDsoh5Z1BFAEFs4Xs=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk=
-github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
-github.com/Azure/go-autorest/autorest/azure/auth v0.5.7 h1:8DQB8yl7aLQuP+nuR5e2RO6454OvFlSTXXaNHshc16s=
+github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
+github.com/Azure/go-autorest/autorest/adal v0.9.17 h1:esOPl2dhcz9P3jqBSJ8tPGEj2EqzPPT6zfyuloiogKY=
+github.com/Azure/go-autorest/autorest/adal v0.9.17/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.7/go.mod h1:AkzUsqkrdmNhfP2i54HqINVQopw0CLDnvHpJ88Zz1eI=
+github.com/Azure/go-autorest/autorest/azure/auth v0.5.9 h1:Y2CgdzitFDsdMwYMzf9LIZWrrTFysqbRc7b94XVVJ78=
+github.com/Azure/go-autorest/autorest/azure/auth v0.5.9/go.mod h1:hg3/1yw0Bq87O3KvvnJoAh34/0zbP7SFizX/qN5JvjU=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
@@ -114,6 +157,7 @@ github.com/DataDog/sketches-go v1.0.0/go.mod h1:O+XkJHWk9w4hDwY2ZUDU31ZC9sNYlYo8
github.com/FZambia/sentinel v1.0.0 h1:KJ0ryjKTZk5WMp0dXvSdNqp3lFaW1fNFuEYfrkLOYIc=
github.com/FZambia/sentinel v1.0.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
github.com/GoogleCloudPlatform/cloudsql-proxy v1.22.0/go.mod h1:mAm5O/zik2RFmcpigNjg6nMotDL8ZXJaxKzgGVcSMFA=
+github.com/GoogleCloudPlatform/cloudsql-proxy v1.29.0/go.mod h1:spvB9eLJH9dutlbPSRmHvSXXHOwGRyeXh1jVdquA2G8=
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/HdrHistogram/hdrhistogram-go v1.1.1 h1:cJXY5VLMHgejurPjZH6Fo9rIwRGLefBGdiaENZALqrg=
github.com/HdrHistogram/hdrhistogram-go v1.1.1/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
@@ -137,15 +181,8 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
-github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
-github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
-github.com/alecthomas/chroma v0.7.3 h1:NfdAERMy+esYQs8OXk0I868/qDxxCEo7FMz1WIqMAeI=
-github.com/alecthomas/chroma v0.7.3/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
-github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
-github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
-github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
-github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
-github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
+github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
+github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -169,12 +206,53 @@ github.com/aws/aws-sdk-go v1.17.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
-github.com/aws/aws-sdk-go v1.38.35 h1:7AlAO0FC+8nFjxiGKEmq0QLpiA8/XFr6eIxgRTwkdTg=
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
+github.com/aws/aws-sdk-go v1.43.31 h1:yJZIr8nMV1hXjAvvOLUFqZRJcHV7udPQBfhJqawDzI0=
+github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
+github.com/aws/aws-sdk-go-v2 v1.16.2 h1:fqlCk6Iy3bnCumtrLz9r3mJ/2gUT0pJ0wLFVIdWh+JA=
+github.com/aws/aws-sdk-go-v2 v1.16.2/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1 h1:SdK4Ppk5IzLs64ZMvr6MrSficMtjY2oS0WOORXTlxwU=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1/go.mod h1:n8Bs1ElDD2wJ9kCRTczA83gYbBmjSwZp3umc6zF4EeM=
+github.com/aws/aws-sdk-go-v2/config v1.15.3 h1:5AlQD0jhVXlGzwo+VORKiUuogkG7pQcLJNzIzK7eodw=
+github.com/aws/aws-sdk-go-v2/config v1.15.3/go.mod h1:9YL3v07Xc/ohTsxFXzan9ZpFpdTOFl4X65BAKYaz8jg=
+github.com/aws/aws-sdk-go-v2/credentials v1.11.2 h1:RQQ5fzclAKJyY5TvF+fkjJEwzK4hnxQCLOu5JXzDmQo=
+github.com/aws/aws-sdk-go-v2/credentials v1.11.2/go.mod h1:j8YsY9TXTm31k4eFhspiQicfXPLZ0gYXA50i4gxPE8g=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.3 h1:LWPg5zjHV9oz/myQr4wMs0gi4CjnDN/ILmyZUFYXZsU=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.3/go.mod h1:uk1vhHHERfSVCUnqSqz8O48LBYDSC+k6brng09jcMOk=
+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.3 h1:ir7iEq78s4txFGgwcLqD6q9IIPzTQNRJXulJd9h/zQo=
+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.3/go.mod h1:0dHuD2HZZSiwfJSy1FO5bX1hQ1TxVV1QXXjpn3XUE44=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.9 h1:onz/VaaxZ7Z4V+WIN9Txly9XLTmoOh1oJ8XcAC3pako=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.9/go.mod h1:AnVH5pvai0pAF4lXRq0bmhbes1u9R8wTE+g+183bZNM=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.3 h1:9stUQR/u2KXU6HkFJYlqnZEjBnbgrVbG6I5HN09xZh0=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.3/go.mod h1:ssOhaLpRlh88H3UmEcsBoVKq309quMvm3Ds8e9d4eJM=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.3.10 h1:by9P+oy3P/CwggN4ClnW2D4oL91QV7pBzBICi1chZvQ=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.3.10/go.mod h1:8DcYQcz0+ZJaSxANlHIsbbi6S+zMwjwdDqwW3r9AzaE=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1 h1:T4pFel53bkHjL2mMo+4DKE6r6AuoZnM0fg7k1/ratr4=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1/go.mod h1:GeUru+8VzrTXV/83XyMJ80KpH8xO89VPoUileyNQ+tc=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.3 h1:I0dcwWitE752hVSMrsLCxqNQ+UdEp3nACx2bYNMQq+k=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.3/go.mod h1:Seb8KNmD6kVTjwRjVEgOT5hPin6sq+v4C2ycJQDwuH8=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.3 h1:Gh1Gpyh01Yvn7ilO/b/hr01WgNpaszfbKMUgqM186xQ=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.3/go.mod h1:wlY6SVjuwvh3TVRpTqdy4I1JpBFLX4UGeKZdWntaocw=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.3 h1:BKjwCJPnANbkwQ8vzSbaZDKawwagDubrH/z/c0X+kbQ=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.3/go.mod h1:Bm/v2IaN6rZ+Op7zX+bOUMdL4fsrYZiD0dsjLhNKwZc=
+github.com/aws/aws-sdk-go-v2/service/kms v1.16.3/go.mod h1:QuiHPBqlOFCi4LqdSskYYAWpQlx3PKmohy+rE2F+o5g=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.26.3 h1:rMPtwA7zzkSQZhhz9U3/SoIDz/NZ7Q+iRn4EIO8rSyU=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.26.3/go.mod h1:g1qvDuRsJY+XghsV6zg00Z4KJ7DtFFCx8fJD2a491Ak=
+github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.4/go.mod h1:PJc8s+lxyU8rrre0/4a0pn2wgwiDvOEzoOjcJUBr67o=
+github.com/aws/aws-sdk-go-v2/service/sns v1.17.4/go.mod h1:kElt+uCcXxcqFyc+bQqZPFD9DME/eC6oHBXvFzQ9Bcw=
+github.com/aws/aws-sdk-go-v2/service/sqs v1.18.3/go.mod h1:skmQo0UPvsjsuYYSYMVmrPc1HWCbHUJyrCEp+ZaLzqM=
+github.com/aws/aws-sdk-go-v2/service/ssm v1.24.1/go.mod h1:NR/xoKjdbRJ+qx0pMR4mI+N/H1I1ynHwXnO6FowXJc0=
+github.com/aws/aws-sdk-go-v2/service/sso v1.11.3 h1:frW4ikGcxfAEDfmQqWgMLp+F1n4nRo9sF39OcIb5BkQ=
+github.com/aws/aws-sdk-go-v2/service/sso v1.11.3/go.mod h1:7UQ/e69kU7LDPtY40OyoHYgRmgfGM4mgsLYtcObdveU=
+github.com/aws/aws-sdk-go-v2/service/sts v1.16.3 h1:cJGRyzCSVwZC7zZZ1xbx9m32UnrKydRYhOvcD1NYP9Q=
+github.com/aws/aws-sdk-go-v2/service/sts v1.16.3/go.mod h1:bfBj0iVmsUyUg4weDB4NxktD9rDGeKSVWnjTnwbx9b8=
+github.com/aws/smithy-go v1.11.2 h1:eG/N+CcUMAvsdffgMvjMKwfyDzIkjM6pfxMJ8Mzc6mE=
+github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw=
github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
+github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -208,7 +286,11 @@ github.com/cloudflare/tableflip v1.2.2/go.mod h1:P4gRehmV6Z2bY5ao5ml9Pd8u6kuEnlB
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
@@ -222,19 +304,19 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.1/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
-github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
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-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU=
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -247,8 +329,9 @@ github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
-github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
-github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
+github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
+github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
+github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dpotapov/go-spnego v0.0.0-20190506202455-c2c609116ad0/go.mod h1:P4f4MSk7h52F2PK0lCapn5+fu47Uf8aRdxDSqgezxZE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -268,6 +351,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
@@ -276,13 +360,13 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
-github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getsentry/raven-go v0.1.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/raven-go v0.1.2/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -297,6 +381,7 @@ github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NB
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/gin-gonic/gin v1.7.3/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/git-lfs/git-lfs v1.5.1-0.20210304194248-2e1d981afbe3/go.mod h1:8Xqs4mqL7o6xEnaXckIgELARTeK7RYtm3pBab7S79Js=
github.com/git-lfs/gitobj/v2 v2.0.1/go.mod h1:q6aqxl6Uu3gWsip5GEKpw+7459F97er8COmU45ncAxw=
@@ -356,9 +441,11 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
+github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw=
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
@@ -416,13 +503,16 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
-github.com/google/go-replayers/grpcreplay v1.0.0 h1:B5kVOzJ1hBgnevTgIWhSTatQ3608yu/2NnU0Ta1d0kY=
github.com/google/go-replayers/grpcreplay v1.0.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
-github.com/google/go-replayers/httpreplay v0.1.2 h1:HCfx+dQzwN9XbGTHF8qJ+67WN8glL9FTWV5rraCJ/jU=
+github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
+github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
github.com/google/go-replayers/httpreplay v0.1.2/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
+github.com/google/go-replayers/httpreplay v1.1.1 h1:H91sIMlt1NZzN7R+/ASswyouLJfW0WLW7fhyUFvDEkY=
+github.com/google/go-replayers/httpreplay v1.1.1/go.mod h1:gN9GeLIs7l6NUoVaSSnv2RiqK1NiwAmD0MrKeC9IIks=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -432,6 +522,8 @@ github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.m
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
+github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
+github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -445,6 +537,7 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210125172800-10e9aeb4a998/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
@@ -456,13 +549,17 @@ github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/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/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
-github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
+github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
+github.com/googleapis/gax-go/v2 v2.2.0 h1:s7jOdKSaksJVOxE0Y/S32otcfiP+UQ0cL8/GTKaONwE=
+github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
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=
@@ -481,6 +578,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok=
+github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -532,6 +631,7 @@ github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfG
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
+github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
@@ -551,15 +651,18 @@ github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCM
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
+github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M=
+github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
@@ -618,6 +721,7 @@ github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -631,6 +735,7 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
@@ -641,6 +746,7 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/libgit2/git2go v0.0.0-20190104134018-ecaeb7a21d47/go.mod h1:4bKN42efkbNYMZlvDfxGDxzl066GhpvIircZDsm8Y+Y=
github.com/libgit2/git2go/v31 v31.4.12/go.mod h1:c/rkJcBcUFx6wHaT++UwNpKvIsmPNqCeQ/vzO4DrEec=
github.com/libgit2/git2go/v33 v33.0.9/go.mod h1:KdpqkU+6+++4oHna/MIOgx4GCQ92IPCdpVRMRI80J+4=
@@ -661,8 +767,10 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
+github.com/mattn/go-ieproxy v0.0.3/go.mod h1:6ZpRmhBaYuBX1U2za+9rC9iCGLsSp2tftelZne7CPko=
+github.com/mattn/go-ieproxy v0.0.6 h1:tVDlituRyeHMMkHpGpUu8CJG+hxPMwbYCkIUK2PUCbo=
+github.com/mattn/go-ieproxy v0.0.6/go.mod h1:6ZpRmhBaYuBX1U2za+9rC9iCGLsSp2tftelZne7CPko=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -670,7 +778,6 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@@ -699,6 +806,7 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -706,6 +814,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/montanaflynn/stats v0.0.0-20151014174947-eeaced052adb/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -769,6 +878,7 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pires/go-proxyproto v0.5.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
+github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.0.0-20170505043639-c605e284fe17/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=
@@ -838,7 +948,6 @@ github.com/sebest/xff v0.0.0-20160910043805-6c115e0ffa35/go.mod h1:wozgYq9WEBQBa
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a h1:iLcLb5Fwwz7g/DLK89F+uQBDeAhHhwdzB5fSlVdhGcM=
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a/go.mod h1:wozgYq9WEBQBaIJe4YZ0qTSFAMxmcwBhQH0fO0R34Z0=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
-github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63/go.mod h1:n+VKSARF5y/tS9XFSP7vWDfS+GUC5vs/YT7M5XDTUEM=
github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500 h1:WnNuhiq+FOY3jNj6JXFT+eLN3CQ/oPIsDPRanvwsmbI=
@@ -956,8 +1065,8 @@ gitlab.com/gitlab-org/labkit v0.0.0-20200908084045-45895e129029/go.mod h1:SNfxkf
gitlab.com/gitlab-org/labkit v1.0.0/go.mod h1:nohrYTSLDnZix0ebXZrbZJjymRar8HeV2roWL5/jw2U=
gitlab.com/gitlab-org/labkit v1.4.1/go.mod h1:x5JO5uvdX4t6e/TZXLXZnFL5AcKz2uLLd3uKXZcuO4k=
gitlab.com/gitlab-org/labkit v1.5.0/go.mod h1:1ZuVZpjSpCKUgjLx8P6jzkkQFxJI1thUKr6yKV3p0vY=
-gitlab.com/gitlab-org/labkit v1.14.0 h1:LSrvHgybidPyH8fHnsy1GBghrLR4kFObFrtZwUfCgAI=
-gitlab.com/gitlab-org/labkit v1.14.0/go.mod h1:bcxc4ZpAC+WyACgyKl7FcvT2XXAbl8CrzN6UY+w8cMc=
+gitlab.com/gitlab-org/labkit v1.15.0 h1:rMdhIdONc7bcd5qGRtWav6iInpeDmavDmP9A1tai92k=
+gitlab.com/gitlab-org/labkit v1.15.0/go.mod h1:bcxc4ZpAC+WyACgyKl7FcvT2XXAbl8CrzN6UY+w8cMc=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
@@ -977,21 +1086,26 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
+go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
+go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
-gocloud.dev v0.23.0 h1:u/6F8slWwaZPgGpjpNp0jzH+1P/M2ri7qEP3lFgbqBE=
+go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
gocloud.dev v0.23.0/go.mod h1:zklCCIIo1N9ELkU2S2E7tW8P8eeMU7oGLeQCXdDwx9Q=
+gocloud.dev v0.25.0 h1:Y7vDq8xj7SyM848KXf32Krda2e6jQ4CLh/mTeCSqXtk=
+gocloud.dev v0.25.0/go.mod h1:7HegHVCYZrMiU3IE1qtnzf/vRrDwLYnRNR3EhWX8x9Y=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -1012,14 +1126,17 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/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-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
+golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1063,8 +1180,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
+golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1121,8 +1239,16 @@ golang.org/x/net v0.0.0-20210420210106-798c2154c571/go.mod h1:72T/g9IO56b78aLF+1
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210505214959-0714010a04ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211008194852-3b03d305991f h1:1scJEYZBaF48BaG6tYbtxmLcXqwYGSfGcMoStTqkkIw=
+golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220401154927-543a649e0bdd h1:zYlwaUHTmxuf6H7hwO2dgwqozQmH7zf4x+/qql4oVWc=
+golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1139,8 +1265,13 @@ golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a h1:4Kd8OPUx1xgUwrHDaviWZO8MsgoZTZYC3g+8m16RBww=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a h1:qfl7ob3DIEs3Ml9oLuPwY2N04gymzAW04WsUQHIClgM=
+golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
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=
@@ -1198,7 +1329,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1240,13 +1370,28 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY=
+golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1263,6 +1408,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1382,8 +1528,23 @@ google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59t
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
-google.golang.org/api v0.54.0 h1:ECJUVngj71QI6XEm7b1sAf8BljU5inEhMbKPR8Lxhhk=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
+google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
+google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
+google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
+google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E=
+google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
+google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
+google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
+google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM=
+google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
+google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
+google.golang.org/api v0.68.0/go.mod h1:sOM8pTpwgflXRhz+oC8H2Dr+UcbMqkPPWNJo88Q7TH8=
+google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80=
+google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
+google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
+google.golang.org/api v0.74.0 h1:ExR2D+5TYIrMphWgs5JCgwRhEDlPDXXrLwHHMgPHTXE=
+google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1446,6 +1607,7 @@ google.golang.org/genproto v0.0.0-20210423144448-3a41ef94ed2b/go.mod h1:P3QM42oQ
google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
+google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
@@ -1454,8 +1616,38 @@ google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210813162853-db860fec028c h1:iLQakcwWG3k/++1q/46apVb1sUQ3IqIdn9yUE6eh/xA=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
+google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
+google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220204002441-d6cc3cc0770e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
+google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de h1:9Ti5SG2U4cAcluryUo/sFay3TQKoxiFMfaT0pbizU7k=
+google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1487,8 +1679,11 @@ google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
+google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
+google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -1502,8 +1697,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/DataDog/dd-trace-go.v1 v1.7.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg=
gopkg.in/DataDog/dd-trace-go.v1 v1.30.0/go.mod h1:SnKViq44dv/0gjl9RpkP0Y2G3BJSRkp6eYdCSu39iI8=
gopkg.in/DataDog/dd-trace-go.v1 v1.32.0 h1:DkD0plWEVUB8v/Ru6kRBW30Hy/fRNBC8hPdcExuBZMc=
@@ -1547,8 +1743,9 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
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-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/workhorse/internal/api/api.go b/workhorse/internal/api/api.go
index 8954923ad75..a536435a587 100644
--- a/workhorse/internal/api/api.go
+++ b/workhorse/internal/api/api.go
@@ -156,8 +156,6 @@ type Response struct {
ShowAllRefs bool
// Detects whether an artifact is used for code intelligence
ProcessLsif bool
- // Detects whether LSIF artifact will be parsed with references
- ProcessLsifReferences bool
// The maximum accepted size in bytes of the upload
MaximumSize int64
}
@@ -263,26 +261,22 @@ func (api *API) newRequest(r *http.Request, suffix string) (*http.Request, error
// PreAuthorize performs a pre-authorization check against the API for the given HTTP request
//
-// If `outErr` is set, the other fields will be nil and it should be treated as
-// a 500 error.
+// If the returned *http.Response is not nil, the caller is responsible for closing its body
//
-// If httpResponse is present, the caller is responsible for closing its body
-//
-// authResponse will only be present if the authorization check was successful
-func (api *API) PreAuthorize(suffix string, r *http.Request) (httpResponse *http.Response, authResponse *Response, outErr error) {
+// Only upon successful authorization do we return a non-nil *Response
+func (api *API) PreAuthorize(suffix string, r *http.Request) (_ *http.Response, _ *Response, err error) {
authReq, err := api.newRequest(r, suffix)
if err != nil {
return nil, nil, fmt.Errorf("preAuthorizeHandler newUpstreamRequest: %v", err)
}
- httpResponse, err = api.doRequestWithoutRedirects(authReq)
+ httpResponse, err := api.doRequestWithoutRedirects(authReq)
if err != nil {
return nil, nil, fmt.Errorf("preAuthorizeHandler: do request: %v", err)
}
defer func() {
- if outErr != nil {
+ if err != nil {
httpResponse.Body.Close()
- httpResponse = nil
}
}()
requestsCounter.WithLabelValues(strconv.Itoa(httpResponse.StatusCode), authReq.Method).Inc()
@@ -293,17 +287,43 @@ func (api *API) PreAuthorize(suffix string, r *http.Request) (httpResponse *http
return httpResponse, nil, nil
}
- authResponse = &Response{}
+ authResponse := &Response{}
// The auth backend validated the client request and told us additional
// request metadata. We must extract this information from the auth
// response body.
if err := json.NewDecoder(httpResponse.Body).Decode(authResponse); err != nil {
- return httpResponse, nil, fmt.Errorf("preAuthorizeHandler: decode authorization response: %v", err)
+ return nil, nil, fmt.Errorf("preAuthorizeHandler: decode authorization response: %v", err)
}
return httpResponse, authResponse, nil
}
+// PreAuthorizeFixedPath makes an internal Workhorse API call to a fixed
+// path, using the HTTP headers of r.
+func (api *API) PreAuthorizeFixedPath(r *http.Request, method string, path string) (*Response, error) {
+ authReq, err := http.NewRequestWithContext(r.Context(), method, api.URL.String(), nil)
+ if err != nil {
+ return nil, fmt.Errorf("construct auth request: %w", err)
+ }
+ authReq.Header = helper.HeaderClone(r.Header)
+
+ failureResponse, apiResponse, err := api.PreAuthorize(path, authReq)
+ if err != nil {
+ return nil, fmt.Errorf("PreAuthorize: %w", err)
+ }
+
+ // We don't need the contents of failureResponse but we are responsible
+ // for closing it. Part of the reason PreAuthorizeFixedPath exists is to
+ // hide this awkwardness.
+ failureResponse.Body.Close()
+
+ if apiResponse == nil {
+ return nil, fmt.Errorf("no api response: status %d", failureResponse.StatusCode)
+ }
+
+ return apiResponse, nil
+}
+
func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpResponse, authResponse, err := api.PreAuthorize(suffix, r)
diff --git a/workhorse/internal/api/block_test.go b/workhorse/internal/api/block_test.go
index 85ad54f3cfd..0beb401d2f5 100644
--- a/workhorse/internal/api/block_test.go
+++ b/workhorse/internal/api/block_test.go
@@ -1,7 +1,7 @@
package api
import (
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"testing"
@@ -46,7 +46,7 @@ func TestBlocker(t *testing.T) {
rw.Flush()
body := rw.Result().Body
- data, err := ioutil.ReadAll(body)
+ data, err := io.ReadAll(body)
require.NoError(t, err)
require.NoError(t, body.Close())
diff --git a/workhorse/internal/artifacts/entry_test.go b/workhorse/internal/artifacts/entry_test.go
index 800125eec91..709fd5f57a7 100644
--- a/workhorse/internal/artifacts/entry_test.go
+++ b/workhorse/internal/artifacts/entry_test.go
@@ -4,7 +4,6 @@ import (
"archive/zip"
"encoding/base64"
"fmt"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -36,7 +35,7 @@ func testEntryServer(t *testing.T, archive string, entry string) *httptest.Respo
}
func TestDownloadingFromValidArchive(t *testing.T) {
- tempFile, err := ioutil.TempFile("", "uploads")
+ tempFile, err := os.CreateTemp("", "uploads")
require.NoError(t, err)
defer tempFile.Close()
defer os.Remove(tempFile.Name())
@@ -63,9 +62,7 @@ func TestDownloadingFromValidArchive(t *testing.T) {
}
func TestDownloadingFromValidHTTPArchive(t *testing.T) {
- tempDir, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempDir)
+ tempDir := t.TempDir()
f, err := os.Create(filepath.Join(tempDir, "archive.zip"))
require.NoError(t, err)
@@ -97,10 +94,9 @@ func TestDownloadingFromValidHTTPArchive(t *testing.T) {
}
func TestDownloadingNonExistingFile(t *testing.T) {
- tempFile, err := ioutil.TempFile("", "uploads")
+ tempFile, err := os.CreateTemp(t.TempDir(), "uploads")
require.NoError(t, err)
defer tempFile.Close()
- defer os.Remove(tempFile.Name())
archive := zip.NewWriter(tempFile)
defer archive.Close()
@@ -121,9 +117,7 @@ func TestIncompleteApiResponse(t *testing.T) {
}
func TestDownloadingFromNonExistingHTTPArchive(t *testing.T) {
- tempDir, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempDir)
+ tempDir := t.TempDir()
fileServer := httptest.NewServer(http.FileServer(http.Dir(tempDir)))
defer fileServer.Close()
diff --git a/workhorse/internal/badgateway/roundtripper.go b/workhorse/internal/badgateway/roundtripper.go
index 86337e80f28..240a4ebc86b 100644
--- a/workhorse/internal/badgateway/roundtripper.go
+++ b/workhorse/internal/badgateway/roundtripper.go
@@ -4,7 +4,7 @@ import (
"bytes"
"fmt"
"html/template"
- "io/ioutil"
+ "io"
"net/http"
"strings"
"time"
@@ -60,7 +60,7 @@ func (t *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
message, contentType = developmentModeResponse(err)
}
- injectedResponse.Body = ioutil.NopCloser(strings.NewReader(message))
+ injectedResponse.Body = io.NopCloser(strings.NewReader(message))
injectedResponse.Header.Set("Content-Type", contentType)
return injectedResponse, nil
diff --git a/workhorse/internal/badgateway/roundtripper_test.go b/workhorse/internal/badgateway/roundtripper_test.go
index fc7132f9bd7..b59cb8d2c5b 100644
--- a/workhorse/internal/badgateway/roundtripper_test.go
+++ b/workhorse/internal/badgateway/roundtripper_test.go
@@ -2,7 +2,7 @@ package badgateway
import (
"errors"
- "io/ioutil"
+ "io"
"net/http"
"testing"
@@ -45,7 +45,7 @@ func TestErrorPage502(t *testing.T) {
require.NoError(t, err, "perform roundtrip")
defer response.Body.Close()
- body, err := ioutil.ReadAll(response.Body)
+ body, err := io.ReadAll(response.Body)
require.NoError(t, err)
require.Equal(t, tc.contentType, response.Header.Get("content-type"), "content type")
diff --git a/workhorse/internal/config/config.go b/workhorse/internal/config/config.go
index e83f55f43bf..3ce88f449a9 100644
--- a/workhorse/internal/config/config.go
+++ b/workhorse/internal/config/config.go
@@ -120,6 +120,7 @@ type Config struct {
TrustedCIDRsForXForwardedFor []string `toml:"trusted_cidrs_for_x_forwarded_for"`
TrustedCIDRsForPropagation []string `toml:"trusted_cidrs_for_propagation"`
Listeners []ListenerConfig `toml:"listeners"`
+ MetricsListener *ListenerConfig `toml:"metrics_listener"`
}
var DefaultImageResizerConfig = ImageResizerConfig{
diff --git a/workhorse/internal/git/archive.go b/workhorse/internal/git/archive.go
index e1d03828b63..5dcbb7f262e 100644
--- a/workhorse/internal/git/archive.go
+++ b/workhorse/internal/git/archive.go
@@ -7,7 +7,6 @@ package git
import (
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path"
@@ -180,7 +179,7 @@ func prepareArchiveTempfile(dir string, prefix string) (*os.File, error) {
if err := os.MkdirAll(dir, 0700); err != nil {
return nil, err
}
- return ioutil.TempFile(dir, prefix)
+ return os.CreateTemp(dir, prefix)
}
func finalizeCachedArchive(tempFile *os.File, archivePath string) error {
diff --git a/workhorse/internal/git/archive_test.go b/workhorse/internal/git/archive_test.go
index b96d5fdec85..b87800f492c 100644
--- a/workhorse/internal/git/archive_test.go
+++ b/workhorse/internal/git/archive_test.go
@@ -1,8 +1,8 @@
package git
import (
- "io/ioutil"
"net/http/httptest"
+ "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
@@ -40,7 +40,7 @@ func TestParseBasename(t *testing.T) {
}
func TestFinalizeArchive(t *testing.T) {
- tempFile, err := ioutil.TempFile("", "gitlab-workhorse-test")
+ tempFile, err := os.CreateTemp("", "gitlab-workhorse-test")
if err != nil {
t.Fatal(err)
}
diff --git a/workhorse/internal/git/upload-pack_test.go b/workhorse/internal/git/upload-pack_test.go
index 9ffc7117790..d1184f95d88 100644
--- a/workhorse/internal/git/upload-pack_test.go
+++ b/workhorse/internal/git/upload-pack_test.go
@@ -5,10 +5,8 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net"
"net/http/httptest"
- "os"
"path/filepath"
"testing"
"time"
@@ -57,7 +55,7 @@ func TestUploadPackTimesOut(t *testing.T) {
}
defer conn.Close()
- _, _ = io.Copy(ioutil.Discard, conn)
+ _, _ = io.Copy(io.Discard, conn)
return &gitalypb.PostUploadPackWithSidechannelResponse{}, nil
},
})
@@ -75,8 +73,7 @@ func TestUploadPackTimesOut(t *testing.T) {
func startSmartHTTPServer(t testing.TB, s gitalypb.SmartHTTPServiceServer) string {
t.Helper()
- tmp, err := ioutil.TempDir("", "")
- require.NoError(t, err)
+ tmp := t.TempDir()
socket := filepath.Join(tmp, "gitaly.sock")
ln, err := net.Listen("unix", socket)
@@ -90,7 +87,6 @@ func startSmartHTTPServer(t testing.TB, s gitalypb.SmartHTTPServiceServer) strin
t.Cleanup(func() {
srv.GracefulStop()
- require.NoError(t, os.RemoveAll(tmp), "error removing temp dir %q", tmp)
})
return fmt.Sprintf("%s://%s", ln.Addr().Network(), ln.Addr().String())
diff --git a/workhorse/internal/helper/helpers.go b/workhorse/internal/helper/helpers.go
index f9b46181579..33318407f88 100644
--- a/workhorse/internal/helper/helpers.go
+++ b/workhorse/internal/helper/helpers.go
@@ -3,7 +3,7 @@ package helper
import (
"bytes"
"errors"
- "io/ioutil"
+ "io"
"mime"
"net"
"net/http"
@@ -197,12 +197,12 @@ func ReadRequestBody(w http.ResponseWriter, r *http.Request, maxBodySize int64)
limitedBody := http.MaxBytesReader(w, r.Body, maxBodySize)
defer limitedBody.Close()
- return ioutil.ReadAll(limitedBody)
+ return io.ReadAll(limitedBody)
}
func CloneRequestWithNewBody(r *http.Request, body []byte) *http.Request {
newReq := *r
- newReq.Body = ioutil.NopCloser(bytes.NewReader(body))
+ newReq.Body = io.NopCloser(bytes.NewReader(body))
newReq.Header = HeaderClone(r.Header)
newReq.ContentLength = int64(len(body))
return &newReq
diff --git a/workhorse/internal/helper/tempfile.go b/workhorse/internal/helper/tempfile.go
index d8fc0d44698..f5864f549d0 100644
--- a/workhorse/internal/helper/tempfile.go
+++ b/workhorse/internal/helper/tempfile.go
@@ -2,12 +2,11 @@ package helper
import (
"io"
- "io/ioutil"
"os"
)
func ReadAllTempfile(r io.Reader) (tempfile *os.File, err error) {
- tempfile, err = ioutil.TempFile("", "gitlab-workhorse-read-all-tempfile")
+ tempfile, err = os.CreateTemp("", "gitlab-workhorse-read-all-tempfile")
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/helper/writeafterreader.go b/workhorse/internal/helper/writeafterreader.go
index 7df2279a86a..3626d70e493 100644
--- a/workhorse/internal/helper/writeafterreader.go
+++ b/workhorse/internal/helper/writeafterreader.go
@@ -3,7 +3,6 @@ package helper
import (
"fmt"
"io"
- "io/ioutil"
"os"
"sync"
)
@@ -131,7 +130,7 @@ func (w *coupledWriter) tempfileWrite(data []byte) (int, error) {
}
func (*coupledWriter) newTempfile() (tempfile *os.File, err error) {
- tempfile, err = ioutil.TempFile("", "gitlab-workhorse-coupledWriter")
+ tempfile, err = os.CreateTemp("", "gitlab-workhorse-coupledWriter")
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/helper/writeafterreader_test.go b/workhorse/internal/helper/writeafterreader_test.go
index 67cb3e6e542..c3da428184b 100644
--- a/workhorse/internal/helper/writeafterreader_test.go
+++ b/workhorse/internal/helper/writeafterreader_test.go
@@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"testing"
"testing/iotest"
)
@@ -14,7 +13,7 @@ func TestBusyReader(t *testing.T) {
r := testReader(testData)
br, _ := NewWriteAfterReader(r, &bytes.Buffer{})
- result, err := ioutil.ReadAll(br)
+ result, err := io.ReadAll(br)
if err != nil {
t.Fatal(err)
}
@@ -27,7 +26,7 @@ func TestBusyReader(t *testing.T) {
func TestFirstWriteAfterReadDone(t *testing.T) {
writeRecorder := &bytes.Buffer{}
br, cw := NewWriteAfterReader(&bytes.Buffer{}, writeRecorder)
- if _, err := io.Copy(ioutil.Discard, br); err != nil {
+ if _, err := io.Copy(io.Discard, br); err != nil {
t.Fatalf("copy from busyreader: %v", err)
}
testData := "test data"
@@ -53,7 +52,7 @@ func TestWriteDelay(t *testing.T) {
}
// Unblock the coupled writer by draining the reader
- if _, err := io.Copy(ioutil.Discard, br); err != nil {
+ if _, err := io.Copy(io.Discard, br); err != nil {
t.Fatalf("copy from busyreader: %v", err)
}
// Now it is no longer an error if 'w' receives a Write()
diff --git a/workhorse/internal/httprs/httprs.go b/workhorse/internal/httprs/httprs.go
index a38230c1968..f7767d2ee28 100644
--- a/workhorse/internal/httprs/httprs.go
+++ b/workhorse/internal/httprs/httprs.go
@@ -20,7 +20,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"github.com/mitchellh/copystructure"
@@ -148,7 +147,7 @@ func (r *HttpReadSeeker) Seek(offset int64, whence int) (int64, error) {
if r.r != nil {
// Try to read, which is cheaper than doing a request
if r.pos < offset && offset-r.pos <= shortSeekBytes {
- _, err := io.CopyN(ioutil.Discard, r, offset-r.pos)
+ _, err := io.CopyN(io.Discard, r, offset-r.pos)
if err != nil {
return 0, err
}
diff --git a/workhorse/internal/httprs/httprs_test.go b/workhorse/internal/httprs/httprs_test.go
index e26d2d21215..9dcfe75219b 100644
--- a/workhorse/internal/httprs/httprs_test.go
+++ b/workhorse/internal/httprs/httprs_test.go
@@ -3,7 +3,6 @@ package httprs
import (
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -49,7 +48,7 @@ type fakeRoundTripper struct {
func (f *fakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
fw := &fakeResponseWriter{h: http.Header{}}
var err error
- fw.tmp, err = ioutil.TempFile(os.TempDir(), "httprs")
+ fw.tmp, err = os.CreateTemp(os.TempDir(), "httprs")
if err != nil {
return nil, err
}
@@ -79,7 +78,7 @@ type RSFactory func() *HttpReadSeeker
func newRSFactory(flags int) RSFactory {
return func() *HttpReadSeeker {
- tmp, err := ioutil.TempFile(os.TempDir(), "httprs")
+ tmp, err := os.CreateTemp(os.TempDir(), "httprs")
if err != nil {
return nil
}
@@ -111,11 +110,9 @@ func newRSFactory(flags int) RSFactory {
func TestHttpWebServer(t *testing.T) {
Convey("Scenario: testing WebServer", t, func() {
- dir, err := ioutil.TempDir("", "webserver")
- So(err, ShouldBeNil)
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
- err = ioutil.WriteFile(filepath.Join(dir, "file"), make([]byte, 10000), 0755)
+ err := os.WriteFile(filepath.Join(dir, "file"), make([]byte, 10000), 0755)
So(err, ShouldBeNil)
server := httptest.NewServer(http.FileServer(http.Dir(dir)))
diff --git a/workhorse/internal/imageresizer/image_resizer_test.go b/workhorse/internal/imageresizer/image_resizer_test.go
index 8f5c8b2a6eb..f16df77f002 100644
--- a/workhorse/internal/imageresizer/image_resizer_test.go
+++ b/workhorse/internal/imageresizer/image_resizer_test.go
@@ -5,7 +5,7 @@ import (
"encoding/json"
"image"
"image/png"
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"os"
@@ -184,7 +184,7 @@ func TestServeOriginalImageWhenSourceImageFormatIsNotAllowed(t *testing.T) {
cfg := config.DefaultImageResizerConfig
// SVG images are not allowed to be resized
svgImagePath := "../../testdata/image.svg"
- svgImage, err := ioutil.ReadFile(svgImagePath)
+ svgImage, err := os.ReadFile(svgImagePath)
require.NoError(t, err)
// ContentType is no longer used to perform the format validation.
// To make the test more strict, we'll use allowed, but incorrect ContentType.
@@ -193,7 +193,7 @@ func TestServeOriginalImageWhenSourceImageFormatIsNotAllowed(t *testing.T) {
resp := requestScaledImage(t, nil, params, cfg)
require.Equal(t, http.StatusOK, resp.StatusCode)
- responseData, err := ioutil.ReadAll(resp.Body)
+ responseData, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, svgImage, responseData, "expected original image")
}
@@ -201,7 +201,7 @@ func TestServeOriginalImageWhenSourceImageFormatIsNotAllowed(t *testing.T) {
func TestServeOriginalImageWhenSourceImageIsTooSmall(t *testing.T) {
content := []byte("PNG") // 3 bytes only, invalid as PNG/JPEG image
- img, err := ioutil.TempFile("", "*.png")
+ img, err := os.CreateTemp("", "*.png")
require.NoError(t, err)
defer img.Close()
@@ -216,7 +216,7 @@ func TestServeOriginalImageWhenSourceImageIsTooSmall(t *testing.T) {
resp := requestScaledImage(t, nil, params, cfg)
require.Equal(t, http.StatusOK, resp.StatusCode)
- responseData, err := ioutil.ReadAll(resp.Body)
+ responseData, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, content, responseData, "expected original image")
}
diff --git a/workhorse/internal/lsif_transformer/parser/cache.go b/workhorse/internal/lsif_transformer/parser/cache.go
index 395069cd217..ec64fd21aa8 100644
--- a/workhorse/internal/lsif_transformer/parser/cache.go
+++ b/workhorse/internal/lsif_transformer/parser/cache.go
@@ -3,7 +3,6 @@ package parser
import (
"encoding/binary"
"io"
- "io/ioutil"
"os"
)
@@ -15,8 +14,8 @@ type cache struct {
chunkSize int64
}
-func newCache(tempDir, filename string, data interface{}) (*cache, error) {
- f, err := ioutil.TempFile(tempDir, filename)
+func newCache(filename string, data interface{}) (*cache, error) {
+ f, err := os.CreateTemp("", filename)
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/lsif_transformer/parser/cache_test.go b/workhorse/internal/lsif_transformer/parser/cache_test.go
index 23a2ac6e9a9..c5d4479d973 100644
--- a/workhorse/internal/lsif_transformer/parser/cache_test.go
+++ b/workhorse/internal/lsif_transformer/parser/cache_test.go
@@ -1,7 +1,7 @@
package parser
import (
- "io/ioutil"
+ "io"
"testing"
"github.com/stretchr/testify/require"
@@ -13,7 +13,7 @@ type chunk struct {
}
func TestCache(t *testing.T) {
- cache, err := newCache("", "test-chunks", chunk{})
+ cache, err := newCache("test-chunks", chunk{})
require.NoError(t, err)
defer cache.Close()
@@ -21,7 +21,7 @@ func TestCache(t *testing.T) {
require.NoError(t, cache.SetEntry(1, &c))
require.NoError(t, cache.setOffset(0))
- content, err := ioutil.ReadAll(cache.file)
+ content, err := io.ReadAll(cache.file)
require.NoError(t, err)
expected := []byte{0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x2, 0x0}
diff --git a/workhorse/internal/lsif_transformer/parser/docs.go b/workhorse/internal/lsif_transformer/parser/docs.go
index c626e07d3fe..f87bc7fd86c 100644
--- a/workhorse/internal/lsif_transformer/parser/docs.go
+++ b/workhorse/internal/lsif_transformer/parser/docs.go
@@ -35,8 +35,8 @@ type Metadata struct {
Root string `json:"projectRoot"`
}
-func NewDocs(config Config) (*Docs, error) {
- ranges, err := NewRanges(config)
+func NewDocs() (*Docs, error) {
+ ranges, err := NewRanges()
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/lsif_transformer/parser/docs_test.go b/workhorse/internal/lsif_transformer/parser/docs_test.go
index 57dca8e773d..24e3eba8ac5 100644
--- a/workhorse/internal/lsif_transformer/parser/docs_test.go
+++ b/workhorse/internal/lsif_transformer/parser/docs_test.go
@@ -14,7 +14,7 @@ func createLine(id, label, uri string) []byte {
}
func TestParse(t *testing.T) {
- d, err := NewDocs(Config{})
+ d, err := NewDocs()
require.NoError(t, err)
defer d.Close()
@@ -31,7 +31,7 @@ func TestParse(t *testing.T) {
}
func TestParseContainsLine(t *testing.T) {
- d, err := NewDocs(Config{})
+ d, err := NewDocs()
require.NoError(t, err)
defer d.Close()
@@ -44,7 +44,7 @@ func TestParseContainsLine(t *testing.T) {
}
func TestParsingVeryLongLine(t *testing.T) {
- d, err := NewDocs(Config{})
+ d, err := NewDocs()
require.NoError(t, err)
defer d.Close()
diff --git a/workhorse/internal/lsif_transformer/parser/hovers.go b/workhorse/internal/lsif_transformer/parser/hovers.go
index a13c7e4c5c2..33d45829295 100644
--- a/workhorse/internal/lsif_transformer/parser/hovers.go
+++ b/workhorse/internal/lsif_transformer/parser/hovers.go
@@ -2,7 +2,6 @@ package parser
import (
"encoding/json"
- "io/ioutil"
"os"
)
@@ -36,10 +35,8 @@ type ResultSetRef struct {
RefId Id `json:"inV"`
}
-func NewHovers(config Config) (*Hovers, error) {
- tempPath := config.TempPath
-
- file, err := ioutil.TempFile(tempPath, "hovers")
+func NewHovers() (*Hovers, error) {
+ file, err := os.CreateTemp("", "hovers")
if err != nil {
return nil, err
}
@@ -48,7 +45,7 @@ func NewHovers(config Config) (*Hovers, error) {
return nil, err
}
- offsets, err := newCache(tempPath, "hovers-indexes", Offset{})
+ offsets, err := newCache("hovers-indexes", Offset{})
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/lsif_transformer/parser/hovers_test.go b/workhorse/internal/lsif_transformer/parser/hovers_test.go
index 3037be103af..5b2166c07a1 100644
--- a/workhorse/internal/lsif_transformer/parser/hovers_test.go
+++ b/workhorse/internal/lsif_transformer/parser/hovers_test.go
@@ -19,7 +19,7 @@ func TestHoversRead(t *testing.T) {
}
func setupHovers(t *testing.T) *Hovers {
- h, err := NewHovers(Config{})
+ h, err := NewHovers()
require.NoError(t, err)
require.NoError(t, h.Read("hoverResult", []byte(`{"id":"2","label":"hoverResult","result":{"contents": ["hello"]}}`)))
diff --git a/workhorse/internal/lsif_transformer/parser/parser.go b/workhorse/internal/lsif_transformer/parser/parser.go
index 085e7a856aa..2e4f925950c 100644
--- a/workhorse/internal/lsif_transformer/parser/parser.go
+++ b/workhorse/internal/lsif_transformer/parser/parser.go
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"gitlab.com/gitlab-org/labkit/log"
@@ -22,18 +21,14 @@ type Parser struct {
pr *io.PipeReader
}
-type Config struct {
- TempPath string
-}
-
-func NewParser(ctx context.Context, r io.Reader, config Config) (io.ReadCloser, error) {
- docs, err := NewDocs(config)
+func NewParser(ctx context.Context, r io.Reader) (io.ReadCloser, error) {
+ docs, err := NewDocs()
if err != nil {
return nil, err
}
// ZIP files need to be seekable. Don't hold it all in RAM, use a tempfile
- tempFile, err := ioutil.TempFile(config.TempPath, Lsif)
+ tempFile, err := os.CreateTemp("", Lsif)
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/lsif_transformer/parser/parser_test.go b/workhorse/internal/lsif_transformer/parser/parser_test.go
index 3a4d72360e2..6887f699cb3 100644
--- a/workhorse/internal/lsif_transformer/parser/parser_test.go
+++ b/workhorse/internal/lsif_transformer/parser/parser_test.go
@@ -6,7 +6,6 @@ import (
"context"
"encoding/json"
"io"
- "io/ioutil"
"os"
"path/filepath"
"testing"
@@ -26,13 +25,13 @@ func TestGenerate(t *testing.T) {
}
func verifyCorrectnessOf(t *testing.T, tmpDir, fileName string) {
- file, err := ioutil.ReadFile(filepath.Join(tmpDir, fileName))
+ file, err := os.ReadFile(filepath.Join(tmpDir, fileName))
require.NoError(t, err)
var buf bytes.Buffer
require.NoError(t, json.Indent(&buf, file, "", " "))
- expected, err := ioutil.ReadFile(filepath.Join("testdata/expected/", fileName))
+ expected, err := os.ReadFile(filepath.Join("testdata/expected/", fileName))
require.NoError(t, err)
require.Equal(t, string(expected), buf.String())
@@ -43,7 +42,7 @@ func createFiles(t *testing.T, filePath, tmpDir string) {
file, err := os.Open(filePath)
require.NoError(t, err)
- parser, err := NewParser(context.Background(), file, Config{})
+ parser, err := NewParser(context.Background(), file)
require.NoError(t, err)
zipFileName := tmpDir + ".zip"
diff --git a/workhorse/internal/lsif_transformer/parser/performance_test.go b/workhorse/internal/lsif_transformer/parser/performance_test.go
index 5a12d90072f..f4adb7a52be 100644
--- a/workhorse/internal/lsif_transformer/parser/performance_test.go
+++ b/workhorse/internal/lsif_transformer/parser/performance_test.go
@@ -3,7 +3,6 @@ package parser
import (
"context"
"io"
- "io/ioutil"
"os"
"runtime"
"testing"
@@ -22,10 +21,10 @@ func BenchmarkGenerate(b *testing.B) {
file, err := os.Open(filePath)
require.NoError(b, err)
- parser, err := NewParser(context.Background(), file, Config{})
+ parser, err := NewParser(context.Background(), file)
require.NoError(b, err)
- _, err = io.Copy(ioutil.Discard, parser)
+ _, err = io.Copy(io.Discard, parser)
require.NoError(b, err)
require.NoError(b, parser.Close())
})
diff --git a/workhorse/internal/lsif_transformer/parser/ranges.go b/workhorse/internal/lsif_transformer/parser/ranges.go
index 3786e15186e..0b4bd588e16 100644
--- a/workhorse/internal/lsif_transformer/parser/ranges.go
+++ b/workhorse/internal/lsif_transformer/parser/ranges.go
@@ -50,18 +50,18 @@ type SerializedRange struct {
References []SerializedReference `json:"references,omitempty"`
}
-func NewRanges(config Config) (*Ranges, error) {
- hovers, err := NewHovers(config)
+func NewRanges() (*Ranges, error) {
+ hovers, err := NewHovers()
if err != nil {
return nil, err
}
- references, err := NewReferences(config)
+ references, err := NewReferences()
if err != nil {
return nil, err
}
- cache, err := newCache(config.TempPath, "ranges", Range{})
+ cache, err := newCache("ranges", Range{})
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/lsif_transformer/parser/ranges_test.go b/workhorse/internal/lsif_transformer/parser/ranges_test.go
index c1400ba61da..807945b41b1 100644
--- a/workhorse/internal/lsif_transformer/parser/ranges_test.go
+++ b/workhorse/internal/lsif_transformer/parser/ranges_test.go
@@ -42,7 +42,7 @@ func TestSerialize(t *testing.T) {
}
func setup(t *testing.T) (*Ranges, func()) {
- r, err := NewRanges(Config{})
+ r, err := NewRanges()
require.NoError(t, err)
require.NoError(t, r.Read("range", []byte(`{"id":1,"label":"range","start":{"line":1,"character":2}}`)))
diff --git a/workhorse/internal/lsif_transformer/parser/references.go b/workhorse/internal/lsif_transformer/parser/references.go
index 39c34105fd1..815f6dfff49 100644
--- a/workhorse/internal/lsif_transformer/parser/references.go
+++ b/workhorse/internal/lsif_transformer/parser/references.go
@@ -19,15 +19,13 @@ type SerializedReference struct {
Path string `json:"path"`
}
-func NewReferences(config Config) (*References, error) {
- tempPath := config.TempPath
-
- items, err := newCache(tempPath, "references", Item{})
+func NewReferences() (*References, error) {
+ items, err := newCache("references", Item{})
if err != nil {
return nil, err
}
- offsets, err := newCache(tempPath, "references-offsets", ReferencesOffset{})
+ offsets, err := newCache("references-offsets", ReferencesOffset{})
if err != nil {
return nil, err
}
diff --git a/workhorse/internal/lsif_transformer/parser/references_test.go b/workhorse/internal/lsif_transformer/parser/references_test.go
index 7b47513bc53..0bf18e44c01 100644
--- a/workhorse/internal/lsif_transformer/parser/references_test.go
+++ b/workhorse/internal/lsif_transformer/parser/references_test.go
@@ -12,7 +12,7 @@ func TestReferencesStore(t *testing.T) {
refId = 3
)
- r, err := NewReferences(Config{})
+ r, err := NewReferences()
require.NoError(t, err)
err = r.Store(refId, []Item{{Line: 2, DocId: docId}, {Line: 3, DocId: docId}})
@@ -30,7 +30,7 @@ func TestReferencesStore(t *testing.T) {
func TestReferencesStoreEmpty(t *testing.T) {
const refId = 3
- r, err := NewReferences(Config{})
+ r, err := NewReferences()
require.NoError(t, err)
err = r.Store(refId, []Item{})
diff --git a/workhorse/internal/secret/jwt.go b/workhorse/internal/secret/jwt.go
index 804f3a9aba9..ce0de6ca38d 100644
--- a/workhorse/internal/secret/jwt.go
+++ b/workhorse/internal/secret/jwt.go
@@ -7,7 +7,7 @@ import (
)
var (
- DefaultClaims = jwt.StandardClaims{Issuer: "gitlab-workhorse"}
+ DefaultClaims = jwt.RegisteredClaims{Issuer: "gitlab-workhorse"}
)
func JWTTokenString(claims jwt.Claims) (string, error) {
diff --git a/workhorse/internal/secret/secret.go b/workhorse/internal/secret/secret.go
index e8c7c25393c..664f07a52c0 100644
--- a/workhorse/internal/secret/secret.go
+++ b/workhorse/internal/secret/secret.go
@@ -3,7 +3,7 @@ package secret
import (
"encoding/base64"
"fmt"
- "io/ioutil"
+ "os"
"sync"
)
@@ -57,7 +57,7 @@ func setBytes() ([]byte, error) {
return theSecret.bytes, nil
}
- base64Bytes, err := ioutil.ReadFile(theSecret.path)
+ base64Bytes, err := os.ReadFile(theSecret.path)
if err != nil {
return nil, fmt.Errorf("secret.setBytes: read %q: %v", theSecret.path, err)
}
diff --git a/workhorse/internal/senddata/contentprocessor/contentprocessor_test.go b/workhorse/internal/senddata/contentprocessor/contentprocessor_test.go
index b009cda1a24..ce7f7921589 100644
--- a/workhorse/internal/senddata/contentprocessor/contentprocessor_test.go
+++ b/workhorse/internal/senddata/contentprocessor/contentprocessor_test.go
@@ -2,7 +2,6 @@ package contentprocessor
import (
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"testing"
@@ -306,7 +305,7 @@ func makeRequest(t *testing.T, handler http.HandlerFunc, body string, dispositio
SetContentHeaders(handler).ServeHTTP(rw, req)
resp := rw.Result()
- respBody, err := ioutil.ReadAll(resp.Body)
+ respBody, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, body, string(respBody))
diff --git a/workhorse/internal/senddata/writer_test.go b/workhorse/internal/senddata/writer_test.go
index fd6f7df5e64..b0c808c6158 100644
--- a/workhorse/internal/senddata/writer_test.go
+++ b/workhorse/internal/senddata/writer_test.go
@@ -2,7 +2,6 @@ package senddata
import (
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"strings"
@@ -47,7 +46,7 @@ func TestWriter(t *testing.T) {
recorder.Flush()
body := recorder.Result().Body
- data, err := ioutil.ReadAll(body)
+ data, err := io.ReadAll(body)
require.NoError(t, err)
require.NoError(t, body.Close())
diff --git a/workhorse/internal/sendfile/sendfile.go b/workhorse/internal/sendfile/sendfile.go
index 75e497f0564..07b1789445a 100644
--- a/workhorse/internal/sendfile/sendfile.go
+++ b/workhorse/internal/sendfile/sendfile.go
@@ -9,7 +9,6 @@ package sendfile
import (
"fmt"
"io"
- "io/ioutil"
"net/http"
"regexp"
@@ -128,7 +127,7 @@ func sendFileFromDisk(w http.ResponseWriter, r *http.Request, file string) {
countSendFileMetrics(fi.Size(), r)
if contentTypeHeaderPresent {
- data, err := ioutil.ReadAll(io.LimitReader(content, headers.MaxDetectSize))
+ data, err := io.ReadAll(io.LimitReader(content, headers.MaxDetectSize))
if err != nil {
helper.Fail500(w, r, fmt.Errorf("content type detection: %v", err))
return
diff --git a/workhorse/internal/sendfile/sendfile_test.go b/workhorse/internal/sendfile/sendfile_test.go
index f01bee0b799..002de7f9f3e 100644
--- a/workhorse/internal/sendfile/sendfile_test.go
+++ b/workhorse/internal/sendfile/sendfile_test.go
@@ -1,9 +1,10 @@
package sendfile
import (
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
+ "os"
"testing"
"github.com/stretchr/testify/require"
@@ -15,7 +16,7 @@ func TestResponseWriter(t *testing.T) {
upstreamResponse := "hello world"
fixturePath := "testdata/sent-file.txt"
- fixtureContent, err := ioutil.ReadFile(fixturePath)
+ fixtureContent, err := os.ReadFile(fixturePath)
require.NoError(t, err)
testCases := []struct {
@@ -52,7 +53,7 @@ func TestResponseWriter(t *testing.T) {
rw.Flush()
body := rw.Result().Body
- data, err := ioutil.ReadAll(body)
+ data, err := io.ReadAll(body)
require.NoError(t, err)
require.NoError(t, body.Close())
@@ -90,7 +91,7 @@ func TestSuccessOverrideContentHeadersFeatureEnabled(t *testing.T) {
func TestSuccessOverrideContentHeadersRangeRequestFeatureEnabled(t *testing.T) {
fixturePath := "../../testdata/forgedfile.png"
- fixtureContent, err := ioutil.ReadFile(fixturePath)
+ fixtureContent, err := os.ReadFile(fixturePath)
require.NoError(t, err)
r, err := http.NewRequest("GET", "/foo", nil)
@@ -113,7 +114,7 @@ func TestSuccessOverrideContentHeadersRangeRequestFeatureEnabled(t *testing.T) {
resp := rw.Result()
body := resp.Body
- data, err := ioutil.ReadAll(body)
+ data, err := io.ReadAll(body)
require.NoError(t, err)
require.NoError(t, body.Close())
@@ -138,7 +139,7 @@ func TestSuccessInlineWhitelistedTypesFeatureEnabled(t *testing.T) {
}
func makeRequest(t *testing.T, fixturePath string, httpHeaders map[string]string) *http.Response {
- fixtureContent, err := ioutil.ReadFile(fixturePath)
+ fixtureContent, err := os.ReadFile(fixturePath)
require.NoError(t, err)
r, err := http.NewRequest("GET", "/foo", nil)
@@ -161,7 +162,7 @@ func makeRequest(t *testing.T, fixturePath string, httpHeaders map[string]string
resp := rw.Result()
body := resp.Body
- data, err := ioutil.ReadAll(body)
+ data, err := io.ReadAll(body)
require.NoError(t, err)
require.NoError(t, body.Close())
diff --git a/workhorse/internal/sendurl/sendurl_test.go b/workhorse/internal/sendurl/sendurl_test.go
index cc77fff0bfd..bca6b7d3075 100644
--- a/workhorse/internal/sendurl/sendurl_test.go
+++ b/workhorse/internal/sendurl/sendurl_test.go
@@ -3,7 +3,6 @@ package sendurl
import (
"encoding/base64"
"fmt"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -40,7 +39,7 @@ func testEntryServer(t *testing.T, requestURL string, httpHeaders http.Header, a
serveFile := func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "GET", r.Method)
- tempFile, err := ioutil.TempFile("", "download_file")
+ tempFile, err := os.CreateTemp("", "download_file")
require.NoError(t, err)
require.NoError(t, os.Remove(tempFile.Name()))
defer tempFile.Close()
diff --git a/workhorse/internal/staticpages/deploy_page.go b/workhorse/internal/staticpages/deploy_page.go
index 35ebafa66e1..3dc2d982981 100644
--- a/workhorse/internal/staticpages/deploy_page.go
+++ b/workhorse/internal/staticpages/deploy_page.go
@@ -1,8 +1,8 @@
package staticpages
import (
- "io/ioutil"
"net/http"
+ "os"
"path/filepath"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
@@ -12,7 +12,7 @@ func (s *Static) DeployPage(handler http.Handler) http.Handler {
deployPage := filepath.Join(s.DocumentRoot, "index.html")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- data, err := ioutil.ReadFile(deployPage)
+ data, err := os.ReadFile(deployPage)
if err != nil {
handler.ServeHTTP(w, r)
return
diff --git a/workhorse/internal/staticpages/deploy_page_test.go b/workhorse/internal/staticpages/deploy_page_test.go
index bc413880184..52ac69da23c 100644
--- a/workhorse/internal/staticpages/deploy_page_test.go
+++ b/workhorse/internal/staticpages/deploy_page_test.go
@@ -1,7 +1,6 @@
package staticpages
import (
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -14,11 +13,7 @@ import (
)
func TestIfNoDeployPageExist(t *testing.T) {
- dir, err := ioutil.TempDir("", "deploy")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
w := httptest.NewRecorder()
@@ -33,14 +28,10 @@ func TestIfNoDeployPageExist(t *testing.T) {
}
func TestIfDeployPageExist(t *testing.T) {
- dir, err := ioutil.TempDir("", "deploy")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
deployPage := "DEPLOY"
- ioutil.WriteFile(filepath.Join(dir, "index.html"), []byte(deployPage), 0600)
+ os.WriteFile(filepath.Join(dir, "index.html"), []byte(deployPage), 0600)
w := httptest.NewRecorder()
diff --git a/workhorse/internal/staticpages/error_pages.go b/workhorse/internal/staticpages/error_pages.go
index 6b86e21940b..e0ba7a5ceef 100644
--- a/workhorse/internal/staticpages/error_pages.go
+++ b/workhorse/internal/staticpages/error_pages.go
@@ -3,8 +3,8 @@ package staticpages
import (
"encoding/json"
"fmt"
- "io/ioutil"
"net/http"
+ "os"
"path/filepath"
"github.com/prometheus/client_golang/prometheus"
@@ -97,7 +97,7 @@ func (s *errorPageResponseWriter) writeHTML() (string, []byte) {
errorPageFile := filepath.Join(s.path, fmt.Sprintf("%d.html", s.status))
// check if custom error page exists, serve this page instead
- if data, err := ioutil.ReadFile(errorPageFile); err == nil {
+ if data, err := os.ReadFile(errorPageFile); err == nil {
return "text/html; charset=utf-8", data
}
}
diff --git a/workhorse/internal/staticpages/error_pages_test.go b/workhorse/internal/staticpages/error_pages_test.go
index c9927668fcc..12c268fb40b 100644
--- a/workhorse/internal/staticpages/error_pages_test.go
+++ b/workhorse/internal/staticpages/error_pages_test.go
@@ -2,7 +2,6 @@ package staticpages
import (
"fmt"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -15,14 +14,10 @@ import (
)
func TestIfErrorPageIsPresented(t *testing.T) {
- dir, err := ioutil.TempDir("", "error_page")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
errorPage := "ERROR"
- ioutil.WriteFile(filepath.Join(dir, "404.html"), []byte(errorPage), 0600)
+ os.WriteFile(filepath.Join(dir, "404.html"), []byte(errorPage), 0600)
w := httptest.NewRecorder()
h := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
@@ -42,11 +37,7 @@ func TestIfErrorPageIsPresented(t *testing.T) {
}
func TestIfErrorPassedIfNoErrorPageIsFound(t *testing.T) {
- dir, err := ioutil.TempDir("", "error_page")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
w := httptest.NewRecorder()
errorResponse := "ERROR"
@@ -63,14 +54,10 @@ func TestIfErrorPassedIfNoErrorPageIsFound(t *testing.T) {
}
func TestIfErrorPageIsIgnoredInDevelopment(t *testing.T) {
- dir, err := ioutil.TempDir("", "error_page")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
errorPage := "ERROR"
- ioutil.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
+ os.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
w := httptest.NewRecorder()
serverError := "Interesting Server Error"
@@ -86,14 +73,10 @@ func TestIfErrorPageIsIgnoredInDevelopment(t *testing.T) {
}
func TestIfErrorPageIsIgnoredIfCustomError(t *testing.T) {
- dir, err := ioutil.TempDir("", "error_page")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
errorPage := "ERROR"
- ioutil.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
+ os.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
w := httptest.NewRecorder()
serverError := "Interesting Server Error"
@@ -121,14 +104,10 @@ func TestErrorPageInterceptedByContentType(t *testing.T) {
}
for _, tc := range testCases {
- dir, err := ioutil.TempDir("", "error_page")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
errorPage := "ERROR"
- ioutil.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
+ os.WriteFile(filepath.Join(dir, "500.html"), []byte(errorPage), 0600)
w := httptest.NewRecorder()
serverError := "Interesting Server Error"
diff --git a/workhorse/internal/staticpages/servefile_test.go b/workhorse/internal/staticpages/servefile_test.go
index 67675beccf8..231c0e59068 100644
--- a/workhorse/internal/staticpages/servefile_test.go
+++ b/workhorse/internal/staticpages/servefile_test.go
@@ -3,7 +3,6 @@ package staticpages
import (
"bytes"
"compress/gzip"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -26,11 +25,7 @@ func TestServingNonExistingFile(t *testing.T) {
}
func TestServingDirectory(t *testing.T) {
- dir, err := ioutil.TempDir("", "deploy")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
httpRequest, _ := http.NewRequest("GET", "/file", nil)
w := httptest.NewRecorder()
@@ -64,16 +59,12 @@ func TestExecutingHandlerWhenNoFileFound(t *testing.T) {
}
func TestServingTheActualFile(t *testing.T) {
- dir, err := ioutil.TempDir("", "deploy")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
httpRequest, _ := http.NewRequest("GET", "/file", nil)
fileContent := "STATIC"
- ioutil.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
+ os.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
w := httptest.NewRecorder()
st := &Static{DocumentRoot: dir}
@@ -121,11 +112,7 @@ func TestExcludedPaths(t *testing.T) {
}
func testServingThePregzippedFile(t *testing.T, enableGzip bool) {
- dir, err := ioutil.TempDir("", "deploy")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
+ dir := t.TempDir()
httpRequest, _ := http.NewRequest("GET", "/file", nil)
@@ -140,8 +127,8 @@ func testServingThePregzippedFile(t *testing.T, enableGzip bool) {
fileGzip.Write([]byte(fileContent))
fileGzip.Close()
- ioutil.WriteFile(filepath.Join(dir, "file.gz"), fileGzipContent.Bytes(), 0600)
- ioutil.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
+ os.WriteFile(filepath.Join(dir, "file.gz"), fileGzipContent.Bytes(), 0600)
+ os.WriteFile(filepath.Join(dir, "file"), []byte(fileContent), 0600)
w := httptest.NewRecorder()
st := &Static{DocumentRoot: dir}
diff --git a/workhorse/internal/testhelper/gitaly.go b/workhorse/internal/testhelper/gitaly.go
index 747d5e6d078..488fb2eaf01 100644
--- a/workhorse/internal/testhelper/gitaly.go
+++ b/workhorse/internal/testhelper/gitaly.go
@@ -4,7 +4,7 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
+ "os"
"path"
"strings"
"sync"
@@ -49,10 +49,10 @@ var (
func init() {
var err error
- if GitalyReceivePackResponseMock, err = ioutil.ReadFile(path.Join(RootDir(), "testdata/receive-pack-fixture.txt")); err != nil {
+ if GitalyReceivePackResponseMock, err = os.ReadFile(path.Join(RootDir(), "testdata/receive-pack-fixture.txt")); err != nil {
log.WithError(err).Fatal("Unable to read pack response")
}
- if GitalyUploadPackResponseMock, err = ioutil.ReadFile(path.Join(RootDir(), "testdata/upload-pack-fixture.txt")); err != nil {
+ if GitalyUploadPackResponseMock, err = os.ReadFile(path.Join(RootDir(), "testdata/upload-pack-fixture.txt")); err != nil {
log.WithError(err).Fatal("Unable to read pack response")
}
}
diff --git a/workhorse/internal/testhelper/testhelper.go b/workhorse/internal/testhelper/testhelper.go
index 6bbdfddcd60..6ea5c1c73e1 100644
--- a/workhorse/internal/testhelper/testhelper.go
+++ b/workhorse/internal/testhelper/testhelper.go
@@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -121,7 +120,7 @@ func RootDir() string {
func LoadFile(t *testing.T, filePath string) string {
t.Helper()
- content, err := ioutil.ReadFile(path.Join(RootDir(), filePath))
+ content, err := os.ReadFile(path.Join(RootDir(), filePath))
require.NoError(t, err)
return string(content)
}
@@ -129,7 +128,7 @@ func LoadFile(t *testing.T, filePath string) string {
func ReadAll(t *testing.T, r io.Reader) []byte {
t.Helper()
- b, err := ioutil.ReadAll(r)
+ b, err := io.ReadAll(r)
require.NoError(t, err)
return b
}
@@ -152,7 +151,7 @@ func ParseJWT(token *jwt.Token) (interface{}, error) {
// UploadClaims represents the JWT claim for upload parameters
type UploadClaims struct {
Upload map[string]string `json:"upload"`
- jwt.StandardClaims
+ jwt.RegisteredClaims
}
func Retry(t testing.TB, timeout time.Duration, fn func() error) {
@@ -176,7 +175,7 @@ func SetupStaticFileHelper(t *testing.T, fpath, content, directory string) strin
require.NoError(t, os.MkdirAll(path.Join(absDocumentRoot, path.Dir(fpath)), 0755), "create document root")
staticFile := path.Join(absDocumentRoot, fpath)
- require.NoError(t, ioutil.WriteFile(staticFile, []byte(content), 0666), "write file content")
+ require.NoError(t, os.WriteFile(staticFile, []byte(content), 0666), "write file content")
return absDocumentRoot
}
diff --git a/workhorse/internal/upload/artifacts_store_test.go b/workhorse/internal/upload/artifacts_store_test.go
index 97e66fc37a4..7032313fbde 100644
--- a/workhorse/internal/upload/artifacts_store_test.go
+++ b/workhorse/internal/upload/artifacts_store_test.go
@@ -6,7 +6,7 @@ import (
"crypto/md5"
"encoding/hex"
"fmt"
- "io/ioutil"
+ "io"
"mime/multipart"
"net/http"
"net/http/httptest"
@@ -56,16 +56,11 @@ func testUploadArtifactsFromTestZip(t *testing.T, ts *httptest.Server) *httptest
}
func TestUploadHandlerSendingToExternalStorage(t *testing.T) {
- tempPath, err := ioutil.TempDir("", "uploads")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempPath)
+ tempPath := t.TempDir()
archiveData, md5 := createTestZipArchive(t)
- archiveFile, err := ioutil.TempFile("", "artifact.zip")
+ archiveFile, err := os.CreateTemp(tempPath, "artifact.zip")
require.NoError(t, err)
- defer os.Remove(archiveFile.Name())
_, err = archiveFile.Write(archiveData)
require.NoError(t, err)
archiveFile.Close()
@@ -75,7 +70,7 @@ func TestUploadHandlerSendingToExternalStorage(t *testing.T) {
storeServerMux.HandleFunc("/url/put", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "PUT", r.Method)
- receivedData, err := ioutil.ReadAll(r.Body)
+ receivedData, err := io.ReadAll(r.Body)
require.NoError(t, err)
require.Equal(t, archiveData, receivedData)
@@ -135,11 +130,7 @@ func TestUploadHandlerSendingToExternalStorage(t *testing.T) {
}
func TestUploadHandlerSendingToExternalStorageAndStorageServerUnreachable(t *testing.T) {
- tempPath, err := ioutil.TempDir("", "uploads")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempPath)
+ tempPath := t.TempDir()
responseProcessor := func(w http.ResponseWriter, r *http.Request) {
t.Fatal("it should not be called")
@@ -161,11 +152,7 @@ func TestUploadHandlerSendingToExternalStorageAndStorageServerUnreachable(t *tes
}
func TestUploadHandlerSendingToExternalStorageAndInvalidURLIsUsed(t *testing.T) {
- tempPath, err := ioutil.TempDir("", "uploads")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempPath)
+ tempPath := t.TempDir()
responseProcessor := func(w http.ResponseWriter, r *http.Request) {
t.Fatal("it should not be called")
diff --git a/workhorse/internal/upload/artifacts_upload_test.go b/workhorse/internal/upload/artifacts_upload_test.go
index 96eb3810673..c94129092c6 100644
--- a/workhorse/internal/upload/artifacts_upload_test.go
+++ b/workhorse/internal/upload/artifacts_upload_test.go
@@ -7,7 +7,6 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"mime/multipart"
"net/http"
"net/http/httptest"
@@ -72,7 +71,7 @@ func testArtifactsUploadServer(t *testing.T, authResponse *api.Response, bodyPro
return
}
- _, err := ioutil.ReadFile(r.FormValue("file.path"))
+ _, err := os.ReadFile(r.FormValue("file.path"))
if err != nil {
t.Fatal("Expected file to be readable")
return
@@ -85,7 +84,7 @@ func testArtifactsUploadServer(t *testing.T, authResponse *api.Response, bodyPro
}
if r.FormValue("metadata.path") != "" {
- metadata, err := ioutil.ReadFile(r.FormValue("metadata.path"))
+ metadata, err := os.ReadFile(r.FormValue("metadata.path"))
if err != nil {
t.Fatal("Expected metadata to be readable")
return
@@ -96,7 +95,7 @@ func testArtifactsUploadServer(t *testing.T, authResponse *api.Response, bodyPro
return
}
defer gz.Close()
- metadata, err = ioutil.ReadAll(gz)
+ metadata, err = io.ReadAll(gz)
if err != nil {
t.Fatal("Expected metadata to be valid")
return
@@ -130,8 +129,7 @@ type testServer struct {
}
func setupWithTmpPath(t *testing.T, filename string, includeFormat bool, format string, authResponse *api.Response, bodyProcessor func(w http.ResponseWriter, r *http.Request)) *testServer {
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
+ tempPath := t.TempDir()
if authResponse == nil {
authResponse = &api.Response{TempPath: tempPath}
@@ -147,7 +145,6 @@ func setupWithTmpPath(t *testing.T, filename string, includeFormat bool, format
cleanup := func() {
ts.Close()
- require.NoError(t, os.RemoveAll(tempPath))
require.NoError(t, writer.Close())
}
@@ -292,8 +289,7 @@ func TestUploadFormProcessing(t *testing.T) {
}
func TestLsifFileProcessing(t *testing.T) {
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
+ tempPath := t.TempDir()
s := setupWithTmpPath(t, "file", true, "zip", &api.Response{TempPath: tempPath, ProcessLsif: true}, nil)
defer s.cleanup()
@@ -312,8 +308,7 @@ func TestLsifFileProcessing(t *testing.T) {
}
func TestInvalidLsifFileProcessing(t *testing.T) {
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
+ tempPath := t.TempDir()
s := setupWithTmpPath(t, "file", true, "zip", &api.Response{TempPath: tempPath, ProcessLsif: true}, nil)
defer s.cleanup()
diff --git a/workhorse/internal/upload/artifacts_uploader.go b/workhorse/internal/upload/artifacts_uploader.go
index c1c49638e21..a8c944a1d33 100644
--- a/workhorse/internal/upload/artifacts_uploader.go
+++ b/workhorse/internal/upload/artifacts_uploader.go
@@ -17,6 +17,7 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/api"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/lsif_transformer/parser"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/destination"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/zipartifacts"
)
@@ -35,7 +36,9 @@ var zipSubcommandsErrorsCounter = promauto.NewCounterVec(
}, []string{"error"})
type artifactsUploadProcessor struct {
- format string
+ format string
+ processLSIF bool
+ tempDir string
SavedFileTracker
}
@@ -43,26 +46,23 @@ type artifactsUploadProcessor struct {
// Artifacts is like a Multipart but specific for artifacts upload.
func Artifacts(myAPI *api.API, h http.Handler, p Preparer) http.Handler {
return myAPI.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) {
- opts, err := p.Prepare(a)
- if err != nil {
- helper.Fail500(w, r, fmt.Errorf("UploadArtifacts: error preparing file storage options"))
- return
- }
-
format := r.URL.Query().Get(ArtifactFormatKey)
-
- mg := &artifactsUploadProcessor{format: format, SavedFileTracker: SavedFileTracker{Request: r}}
- interceptMultipartFiles(w, r, h, a, mg, opts)
+ mg := &artifactsUploadProcessor{
+ format: format,
+ processLSIF: a.ProcessLsif,
+ tempDir: a.TempPath,
+ SavedFileTracker: SavedFileTracker{Request: r},
+ }
+ interceptMultipartFiles(w, r, h, mg, &eagerAuthorizer{a}, p)
}, "/authorize")
}
func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context, file *destination.FileHandler) (*destination.FileHandler, error) {
- metaReader, metaWriter := io.Pipe()
- defer metaWriter.Close()
-
metaOpts := &destination.UploadOpts{
- LocalTempPath: os.TempDir(),
- TempFilePrefix: "metadata.gz",
+ LocalTempPath: a.tempDir,
+ }
+ if metaOpts.LocalTempPath == "" {
+ metaOpts.LocalTempPath = os.TempDir()
}
fileName := file.LocalPath
@@ -73,24 +73,22 @@ func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context,
zipMd := exec.CommandContext(ctx, "gitlab-zip-metadata", fileName)
zipMd.Stderr = log.ContextLogger(ctx).Writer()
zipMd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
- zipMd.Stdout = metaWriter
+
+ zipMdOut, err := zipMd.StdoutPipe()
+ if err != nil {
+ return nil, err
+ }
+ defer zipMdOut.Close()
if err := zipMd.Start(); err != nil {
return nil, err
}
defer helper.CleanUpProcessGroup(zipMd)
- type saveResult struct {
- error
- *destination.FileHandler
+ fh, err := destination.Upload(ctx, zipMdOut, -1, "metadata.gz", metaOpts)
+ if err != nil {
+ return nil, err
}
- done := make(chan saveResult)
- go func() {
- var result saveResult
- result.FileHandler, result.error = destination.Upload(ctx, metaReader, -1, metaOpts)
-
- done <- result
- }()
if err := zipMd.Wait(); err != nil {
st, ok := helper.ExitStatus(err)
@@ -110,17 +108,15 @@ func (a *artifactsUploadProcessor) generateMetadataFromZip(ctx context.Context,
}
}
- metaWriter.Close()
- result := <-done
- return result.FileHandler, result.error
+ return fh, nil
}
func (a *artifactsUploadProcessor) ProcessFile(ctx context.Context, formName string, file *destination.FileHandler, writer *multipart.Writer) error {
// ProcessFile for artifacts requires file form-data field name to eq `file`
-
if formName != "file" {
return fmt.Errorf("invalid form field: %q", formName)
}
+
if a.Count() > 0 {
return fmt.Errorf("artifacts request contains more than one file")
}
@@ -136,7 +132,6 @@ func (a *artifactsUploadProcessor) ProcessFile(ctx context.Context, formName str
return nil
}
- // TODO: can we rely on disk for shipping metadata? Not if we split workhorse and rails in 2 different PODs
metadata, err := a.generateMetadataFromZip(ctx, file)
if err != nil {
return err
@@ -158,6 +153,12 @@ func (a *artifactsUploadProcessor) ProcessFile(ctx context.Context, formName str
return nil
}
-func (a *artifactsUploadProcessor) Name() string {
- return "artifacts"
+func (a *artifactsUploadProcessor) Name() string { return "artifacts" }
+
+func (a *artifactsUploadProcessor) TransformContents(ctx context.Context, filename string, r io.Reader) (io.ReadCloser, error) {
+ if a.processLSIF {
+ return parser.NewParser(ctx, r)
+ }
+
+ return a.SavedFileTracker.TransformContents(ctx, filename, r)
}
diff --git a/workhorse/internal/upload/body_uploader.go b/workhorse/internal/upload/body_uploader.go
index 6fb201fe677..4b5152c283c 100644
--- a/workhorse/internal/upload/body_uploader.go
+++ b/workhorse/internal/upload/body_uploader.go
@@ -2,7 +2,7 @@ package upload
import (
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
"strings"
@@ -23,7 +23,7 @@ func RequestBody(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
return
}
- fh, err := destination.Upload(r.Context(), r.Body, r.ContentLength, opts)
+ fh, err := destination.Upload(r.Context(), r.Body, r.ContentLength, "upload", opts)
if err != nil {
helper.Fail500(w, r, fmt.Errorf("RequestBody: upload failed: %v", err))
return
@@ -42,7 +42,7 @@ func RequestBody(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
// Hijack body
body := data.Encode()
- r.Body = ioutil.NopCloser(strings.NewReader(body))
+ r.Body = io.NopCloser(strings.NewReader(body))
r.ContentLength = int64(len(body))
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
diff --git a/workhorse/internal/upload/body_uploader_test.go b/workhorse/internal/upload/body_uploader_test.go
index 35772be5bc3..837d119e72e 100644
--- a/workhorse/internal/upload/body_uploader_test.go
+++ b/workhorse/internal/upload/body_uploader_test.go
@@ -3,7 +3,6 @@ package upload
import (
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -32,7 +31,7 @@ func TestRequestBody(t *testing.T) {
resp := testUpload(&rails{}, &alwaysLocalPreparer{}, echoProxy(t, fileLen), body)
require.Equal(t, http.StatusOK, resp.StatusCode)
- uploadEcho, err := ioutil.ReadAll(resp.Body)
+ uploadEcho, err := io.ReadAll(resp.Body)
require.NoError(t, err, "Can't read response body")
require.Equal(t, fileContent, string(uploadEcho))
@@ -44,7 +43,7 @@ func TestRequestBodyCustomPreparer(t *testing.T) {
resp := testUpload(&rails{}, &alwaysLocalPreparer{}, echoProxy(t, fileLen), body)
require.Equal(t, http.StatusOK, resp.StatusCode)
- uploadEcho, err := ioutil.ReadAll(resp.Body)
+ uploadEcho, err := io.ReadAll(resp.Body)
require.NoError(t, err, "Can't read response body")
require.Equal(t, fileContent, string(uploadEcho))
}
diff --git a/workhorse/internal/upload/destination/destination.go b/workhorse/internal/upload/destination/destination.go
index b18b6e22a99..5e145e2cb2a 100644
--- a/workhorse/internal/upload/destination/destination.go
+++ b/workhorse/internal/upload/destination/destination.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"strconv"
"time"
@@ -54,7 +53,7 @@ type FileHandler struct {
type uploadClaims struct {
Upload map[string]string `json:"upload"`
- jwt.StandardClaims
+ jwt.RegisteredClaims
}
// SHA256 hash of the handled file
@@ -97,7 +96,7 @@ func (fh *FileHandler) GitLabFinalizeFields(prefix string) (map[string]string, e
signedData[hashName] = hash
}
- claims := uploadClaims{Upload: signedData, StandardClaims: secret.DefaultClaims}
+ claims := uploadClaims{Upload: signedData, RegisteredClaims: secret.DefaultClaims}
jwtData, err := secret.JWTTokenString(claims)
if err != nil {
return nil, err
@@ -113,9 +112,9 @@ type consumer interface {
// Upload persists the provided reader content to all the location specified in opts. A cleanup will be performed once ctx is Done
// Make sure the provided context will not expire before finalizing upload with GitLab Rails.
-func Upload(ctx context.Context, reader io.Reader, size int64, opts *UploadOpts) (*FileHandler, error) {
+func Upload(ctx context.Context, reader io.Reader, size int64, name string, opts *UploadOpts) (*FileHandler, error) {
fh := &FileHandler{
- Name: opts.TempFilePrefix,
+ Name: name,
RemoteID: opts.RemoteID,
RemoteURL: opts.RemoteURL,
}
@@ -199,13 +198,13 @@ func Upload(ctx context.Context, reader io.Reader, size int64, opts *UploadOpts)
}
logger := log.WithContextFields(ctx, log.Fields{
- "copied_bytes": fh.Size,
- "is_local": opts.IsLocalTempFile(),
- "is_multipart": opts.IsMultipart(),
- "is_remote": !opts.IsLocalTempFile(),
- "remote_id": opts.RemoteID,
- "temp_file_prefix": opts.TempFilePrefix,
- "client_mode": clientMode,
+ "copied_bytes": fh.Size,
+ "is_local": opts.IsLocalTempFile(),
+ "is_multipart": opts.IsMultipart(),
+ "is_remote": !opts.IsLocalTempFile(),
+ "remote_id": opts.RemoteID,
+ "client_mode": clientMode,
+ "filename": fh.Name,
})
if opts.IsLocalTempFile() {
@@ -226,7 +225,7 @@ func (fh *FileHandler) newLocalFile(ctx context.Context, opts *UploadOpts) (cons
return nil, fmt.Errorf("newLocalFile: mkdir %q: %v", opts.LocalTempPath, err)
}
- file, err := ioutil.TempFile(opts.LocalTempPath, opts.TempFilePrefix)
+ file, err := os.CreateTemp(opts.LocalTempPath, "gitlab-workhorse-upload")
if err != nil {
return nil, fmt.Errorf("newLocalFile: create file: %v", err)
}
diff --git a/workhorse/internal/upload/destination/destination_test.go b/workhorse/internal/upload/destination/destination_test.go
index ddf0ea24d60..6ebe163468b 100644
--- a/workhorse/internal/upload/destination/destination_test.go
+++ b/workhorse/internal/upload/destination/destination_test.go
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
- "io/ioutil"
"os"
"path"
"strconv"
@@ -43,12 +42,10 @@ func TestUploadWrongSize(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- tmpFolder, err := ioutil.TempDir("", "workhorse-test-tmp")
- require.NoError(t, err)
- defer os.RemoveAll(tmpFolder)
+ tmpFolder := t.TempDir()
- opts := &destination.UploadOpts{LocalTempPath: tmpFolder, TempFilePrefix: "test-file"}
- fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize+1, opts)
+ opts := &destination.UploadOpts{LocalTempPath: tmpFolder}
+ fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize+1, "upload", opts)
require.Error(t, err)
_, isSizeError := err.(destination.SizeError)
require.True(t, isSizeError, "Should fail with SizeError")
@@ -59,12 +56,10 @@ func TestUploadWithKnownSizeExceedLimit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- tmpFolder, err := ioutil.TempDir("", "workhorse-test-tmp")
- require.NoError(t, err)
- defer os.RemoveAll(tmpFolder)
+ tmpFolder := t.TempDir()
- opts := &destination.UploadOpts{LocalTempPath: tmpFolder, TempFilePrefix: "test-file", MaximumSize: test.ObjectSize - 1}
- fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, opts)
+ opts := &destination.UploadOpts{LocalTempPath: tmpFolder, MaximumSize: test.ObjectSize - 1}
+ fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, "upload", opts)
require.Error(t, err)
_, isSizeError := err.(destination.SizeError)
require.True(t, isSizeError, "Should fail with SizeError")
@@ -75,12 +70,10 @@ func TestUploadWithUnknownSizeExceedLimit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- tmpFolder, err := ioutil.TempDir("", "workhorse-test-tmp")
- require.NoError(t, err)
- defer os.RemoveAll(tmpFolder)
+ tmpFolder := t.TempDir()
- opts := &destination.UploadOpts{LocalTempPath: tmpFolder, TempFilePrefix: "test-file", MaximumSize: test.ObjectSize - 1}
- fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), -1, opts)
+ opts := &destination.UploadOpts{LocalTempPath: tmpFolder, MaximumSize: test.ObjectSize - 1}
+ fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), -1, "upload", opts)
require.Equal(t, err, destination.ErrEntityTooLarge)
require.Nil(t, fh)
}
@@ -117,7 +110,7 @@ func TestUploadWrongETag(t *testing.T) {
osStub.InitiateMultipartUpload(test.ObjectPath)
}
ctx, cancel := context.WithCancel(context.Background())
- fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, opts)
+ fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, "upload", opts)
require.Nil(t, fh)
require.Error(t, err)
require.Equal(t, 1, osStub.PutsCnt(), "File not uploaded")
@@ -139,9 +132,7 @@ func TestUpload(t *testing.T) {
remoteMultipart
)
- tmpFolder, err := ioutil.TempDir("", "workhorse-test-tmp")
- require.NoError(t, err)
- defer os.RemoveAll(tmpFolder)
+ tmpFolder := t.TempDir()
tests := []struct {
name string
@@ -191,13 +182,12 @@ func TestUpload(t *testing.T) {
if spec.local {
opts.LocalTempPath = tmpFolder
- opts.TempFilePrefix = "test-file"
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, &opts)
+ fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, "upload", &opts)
require.NoError(t, err)
require.NotNil(t, fh)
@@ -211,9 +201,6 @@ func TestUpload(t *testing.T) {
dir := path.Dir(fh.LocalPath)
require.Equal(t, opts.LocalTempPath, dir)
- filename := path.Base(fh.LocalPath)
- beginsWithPrefix := strings.HasPrefix(filename, opts.TempFilePrefix)
- require.True(t, beginsWithPrefix, fmt.Sprintf("LocalPath filename %q do not begin with TempFilePrefix %q", filename, opts.TempFilePrefix))
} else {
require.Empty(t, fh.LocalPath, "LocalPath must be empty for non local uploads")
}
@@ -291,7 +278,7 @@ func TestUploadWithS3WorkhorseClient(t *testing.T) {
MaximumSize: tc.maxSize,
}
- _, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), tc.objectSize, &opts)
+ _, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), tc.objectSize, "upload", &opts)
if tc.expectedErr == nil {
require.NoError(t, err)
@@ -305,8 +292,7 @@ func TestUploadWithS3WorkhorseClient(t *testing.T) {
}
func TestUploadWithAzureWorkhorseClient(t *testing.T) {
- mux, bucketDir, cleanup := test.SetupGoCloudFileBucket(t, "azblob")
- defer cleanup()
+ mux, bucketDir := test.SetupGoCloudFileBucket(t, "azblob")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -324,7 +310,7 @@ func TestUploadWithAzureWorkhorseClient(t *testing.T) {
},
}
- _, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, &opts)
+ _, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, "upload", &opts)
require.NoError(t, err)
test.GoCloudObjectExists(t, bucketDir, remoteObject)
@@ -349,7 +335,7 @@ func TestUploadWithUnknownGoCloudScheme(t *testing.T) {
},
}
- _, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, &opts)
+ _, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, "upload", &opts)
require.Error(t, err)
}
@@ -375,7 +361,7 @@ func TestUploadMultipartInBodyFailure(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, &opts)
+ fh, err := destination.Upload(ctx, strings.NewReader(test.ObjectContent), test.ObjectSize, "upload", &opts)
require.Nil(t, fh)
require.Error(t, err)
require.EqualError(t, err, test.MultipartUploadInternalError().Error())
@@ -431,10 +417,6 @@ func TestUploadRemoteFileWithLimit(t *testing.T) {
var opts destination.UploadOpts
for _, remoteType := range remoteTypes {
- tmpFolder, err := ioutil.TempDir("", "workhorse-test-tmp")
- require.NoError(t, err)
- defer os.RemoveAll(tmpFolder)
-
osStub, ts := test.StartObjectStore()
defer ts.Close()
@@ -468,7 +450,7 @@ func TestUploadRemoteFileWithLimit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- fh, err := destination.Upload(ctx, strings.NewReader(tc.testData), tc.objectSize, &opts)
+ fh, err := destination.Upload(ctx, strings.NewReader(tc.testData), tc.objectSize, "upload", &opts)
if tc.expectedErr == nil {
require.NoError(t, err)
diff --git a/workhorse/internal/upload/destination/filestore/filestore_test.go b/workhorse/internal/upload/destination/filestore/filestore_test.go
index ec67eae96b9..6f0425809fe 100644
--- a/workhorse/internal/upload/destination/filestore/filestore_test.go
+++ b/workhorse/internal/upload/destination/filestore/filestore_test.go
@@ -2,7 +2,6 @@ package filestore
import (
"context"
- "io/ioutil"
"os"
"strings"
"testing"
@@ -12,7 +11,7 @@ import (
)
func TestConsume(t *testing.T) {
- f, err := ioutil.TempFile("", "filestore-local-file")
+ f, err := os.CreateTemp("", "filestore-local-file")
if f != nil {
defer os.Remove(f.Name())
}
@@ -32,7 +31,7 @@ func TestConsume(t *testing.T) {
require.NoError(t, err)
require.Equal(t, int64(len(content)), n)
- consumedContent, err := ioutil.ReadFile(f.Name())
+ consumedContent, err := os.ReadFile(f.Name())
require.NoError(t, err)
require.Equal(t, content, string(consumedContent))
}
diff --git a/workhorse/internal/upload/destination/objectstore/gocloud_object_test.go b/workhorse/internal/upload/destination/objectstore/gocloud_object_test.go
index 57b3a35b41e..55d886087be 100644
--- a/workhorse/internal/upload/destination/objectstore/gocloud_object_test.go
+++ b/workhorse/internal/upload/destination/objectstore/gocloud_object_test.go
@@ -15,8 +15,7 @@ import (
)
func TestGoCloudObjectUpload(t *testing.T) {
- mux, _, cleanup := test.SetupGoCloudFileBucket(t, "azuretest")
- defer cleanup()
+ mux, _ := test.SetupGoCloudFileBucket(t, "azuretest")
ctx, cancel := context.WithCancel(context.Background())
deadline := time.Now().Add(testTimeout)
diff --git a/workhorse/internal/upload/destination/objectstore/multipart.go b/workhorse/internal/upload/destination/objectstore/multipart.go
index 4c5b64b27ee..df336d2d901 100644
--- a/workhorse/internal/upload/destination/objectstore/multipart.go
+++ b/workhorse/internal/upload/destination/objectstore/multipart.go
@@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
@@ -66,7 +65,7 @@ func (m *Multipart) Upload(ctx context.Context, r io.Reader) error {
}
}
- n, err := io.Copy(ioutil.Discard, r)
+ n, err := io.Copy(io.Discard, r)
if err != nil {
return fmt.Errorf("drain pipe: %v", err)
}
@@ -93,19 +92,19 @@ func (m *Multipart) Delete() {
}
func (m *Multipart) readAndUploadOnePart(ctx context.Context, partURL string, putHeaders map[string]string, src io.Reader, partNumber int) (*completeMultipartUploadPart, error) {
- file, err := ioutil.TempFile("", "part-buffer")
+ file, err := os.CreateTemp("", "part-buffer")
if err != nil {
return nil, fmt.Errorf("create temporary buffer file: %v", err)
}
defer file.Close()
if err := os.Remove(file.Name()); err != nil {
- return nil, err
+ return nil, fmt.Errorf("remove temporary buffer file: %v", err)
}
n, err := io.Copy(file, src)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("copy to temporary buffer file: %v", err)
}
if n == 0 {
return nil, nil
diff --git a/workhorse/internal/upload/destination/objectstore/multipart_test.go b/workhorse/internal/upload/destination/objectstore/multipart_test.go
index 4aff3467e30..2a5161e42e7 100644
--- a/workhorse/internal/upload/destination/objectstore/multipart_test.go
+++ b/workhorse/internal/upload/destination/objectstore/multipart_test.go
@@ -2,7 +2,7 @@ package objectstore_test
import (
"context"
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"strings"
@@ -22,7 +22,7 @@ func TestMultipartUploadWithUpcaseETags(t *testing.T) {
var putCnt, postCnt int
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- _, err := ioutil.ReadAll(r.Body)
+ _, err := io.ReadAll(r.Body)
require.NoError(t, err)
defer r.Body.Close()
diff --git a/workhorse/internal/upload/destination/objectstore/object.go b/workhorse/internal/upload/destination/objectstore/object.go
index b7c4f12f009..68c566861af 100644
--- a/workhorse/internal/upload/destination/objectstore/object.go
+++ b/workhorse/internal/upload/destination/objectstore/object.go
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
"net/http"
"gitlab.com/gitlab-org/labkit/mask"
@@ -53,7 +52,7 @@ func newObject(putURL, deleteURL string, putHeaders map[string]string, size int6
func (o *Object) Upload(ctx context.Context, r io.Reader) error {
// we should prevent pr.Close() otherwise it may shadow error set with pr.CloseWithError(err)
- req, err := http.NewRequest(http.MethodPut, o.putURL, ioutil.NopCloser(r))
+ req, err := http.NewRequest(http.MethodPut, o.putURL, io.NopCloser(r))
if err != nil {
return fmt.Errorf("PUT %q: %v", mask.URL(o.putURL), err)
diff --git a/workhorse/internal/upload/destination/objectstore/s3_object_test.go b/workhorse/internal/upload/destination/objectstore/s3_object_test.go
index b81b0ae2024..0ed14a2e844 100644
--- a/workhorse/internal/upload/destination/objectstore/s3_object_test.go
+++ b/workhorse/internal/upload/destination/objectstore/s3_object_test.go
@@ -4,8 +4,6 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
- "os"
"path/filepath"
"strings"
"sync"
@@ -47,9 +45,7 @@ func TestS3ObjectUpload(t *testing.T) {
defer ts.Close()
deadline := time.Now().Add(testTimeout)
- tmpDir, err := ioutil.TempDir("", "workhorse-test-")
- require.NoError(t, err)
- defer os.Remove(tmpDir)
+ tmpDir := t.TempDir()
objectName := filepath.Join(tmpDir, "s3-test-data")
ctx, cancel := context.WithCancel(context.Background())
@@ -87,9 +83,7 @@ func TestConcurrentS3ObjectUpload(t *testing.T) {
defer artifactsServer.Close()
deadline := time.Now().Add(testTimeout)
- tmpDir, err := ioutil.TempDir("", "workhorse-test-")
- require.NoError(t, err)
- defer os.Remove(tmpDir)
+ tmpDir := t.TempDir()
var wg sync.WaitGroup
@@ -136,9 +130,7 @@ func TestS3ObjectUploadCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
deadline := time.Now().Add(testTimeout)
- tmpDir, err := ioutil.TempDir("", "workhorse-test-")
- require.NoError(t, err)
- defer os.Remove(tmpDir)
+ tmpDir := t.TempDir()
objectName := filepath.Join(tmpDir, "s3-test-data")
@@ -160,9 +152,7 @@ func TestS3ObjectUploadLimitReached(t *testing.T) {
defer ts.Close()
deadline := time.Now().Add(testTimeout)
- tmpDir, err := ioutil.TempDir("", "workhorse-test-")
- require.NoError(t, err)
- defer os.Remove(tmpDir)
+ tmpDir := t.TempDir()
objectName := filepath.Join(tmpDir, "s3-test-data")
object, err := objectstore.NewS3Object(objectName, creds, config)
diff --git a/workhorse/internal/upload/destination/objectstore/s3_session.go b/workhorse/internal/upload/destination/objectstore/s3_session.go
index aa38f18ed7a..d71b38eb22e 100644
--- a/workhorse/internal/upload/destination/objectstore/s3_session.go
+++ b/workhorse/internal/upload/destination/objectstore/s3_session.go
@@ -10,6 +10,8 @@ import (
"github.com/aws/aws-sdk-go/aws/session"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
+
+ "gitlab.com/gitlab-org/labkit/fips"
)
type s3Session struct {
@@ -61,8 +63,9 @@ func setupS3Session(s3Credentials config.S3Credentials, s3Config config.S3Config
}
cfg := &aws.Config{
- Region: aws.String(s3Config.Region),
- S3ForcePathStyle: aws.Bool(s3Config.PathStyle),
+ Region: aws.String(s3Config.Region),
+ S3ForcePathStyle: aws.Bool(s3Config.PathStyle),
+ S3DisableContentMD5Validation: aws.Bool(fips.Enabled()),
}
// In case IAM profiles aren't being used, use the static credentials
diff --git a/workhorse/internal/upload/destination/objectstore/test/gocloud_stub.go b/workhorse/internal/upload/destination/objectstore/test/gocloud_stub.go
index cf22075e407..bff0eabaee5 100644
--- a/workhorse/internal/upload/destination/objectstore/test/gocloud_stub.go
+++ b/workhorse/internal/upload/destination/objectstore/test/gocloud_stub.go
@@ -2,9 +2,7 @@ package test
import (
"context"
- "io/ioutil"
"net/url"
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -20,18 +18,14 @@ func (o *dirOpener) OpenBucketURL(ctx context.Context, u *url.URL) (*blob.Bucket
return fileblob.OpenBucket(o.tmpDir, nil)
}
-func SetupGoCloudFileBucket(t *testing.T, scheme string) (m *blob.URLMux, bucketDir string, cleanup func()) {
- tmpDir, err := ioutil.TempDir("", "")
- require.NoError(t, err)
+func SetupGoCloudFileBucket(t *testing.T, scheme string) (m *blob.URLMux, bucketDir string) {
+ tmpDir := t.TempDir()
mux := new(blob.URLMux)
fake := &dirOpener{tmpDir: tmpDir}
mux.RegisterBucket(scheme, fake)
- cleanup = func() {
- os.RemoveAll(tmpDir)
- }
- return mux, tmpDir, cleanup
+ return mux, tmpDir
}
func GoCloudObjectExists(t *testing.T, bucketDir string, objectName string) {
diff --git a/workhorse/internal/upload/destination/objectstore/test/objectstore_stub.go b/workhorse/internal/upload/destination/objectstore/test/objectstore_stub.go
index d51a2de7456..1a380bd5083 100644
--- a/workhorse/internal/upload/destination/objectstore/test/objectstore_stub.go
+++ b/workhorse/internal/upload/destination/objectstore/test/objectstore_stub.go
@@ -6,7 +6,6 @@ import (
"encoding/xml"
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"strconv"
@@ -22,7 +21,8 @@ type partsEtagMap map[int]string
// Instead of storing objects it will just save md5sum.
type ObjectstoreStub struct {
// bucket contains md5sum of uploaded objects
- bucket map[string]string
+ bucket map[string]string
+ contents map[string][]byte
// overwriteMD5 contains overwrites for md5sum that should be return instead of the regular hash
overwriteMD5 map[string]string
// multipart is a map of MultipartUploads
@@ -48,6 +48,7 @@ func StartObjectStoreWithCustomMD5(md5Hashes map[string]string) (*ObjectstoreStu
multipart: make(map[string]partsEtagMap),
overwriteMD5: make(map[string]string),
headers: make(map[string]*http.Header),
+ contents: make(map[string][]byte),
}
for k, v := range md5Hashes {
@@ -82,6 +83,15 @@ func (o *ObjectstoreStub) GetObjectMD5(path string) string {
return o.bucket[path]
}
+// GetObject returns the contents of the uploaded object. The caller must
+// not modify the byte slice.
+func (o *ObjectstoreStub) GetObject(path string) []byte {
+ o.m.Lock()
+ defer o.m.Unlock()
+
+ return o.contents[path]
+}
+
// GetHeader returns a given HTTP header of the object uploaded to the path
func (o *ObjectstoreStub) GetHeader(path, key string) string {
o.m.Lock()
@@ -154,11 +164,11 @@ func (o *ObjectstoreStub) putObject(w http.ResponseWriter, r *http.Request) {
etag, overwritten := o.overwriteMD5[objectPath]
if !overwritten {
+ buf, _ := io.ReadAll(r.Body)
+ o.contents[objectPath] = buf
hasher := md5.New()
- io.Copy(hasher, r.Body)
-
- checksum := hasher.Sum(nil)
- etag = hex.EncodeToString(checksum)
+ hasher.Write(buf)
+ etag = hex.EncodeToString(hasher.Sum(nil))
}
o.headers[objectPath] = &r.Header
@@ -196,7 +206,7 @@ func (o *ObjectstoreStub) completeMultipartUpload(w http.ResponseWriter, r *http
return
}
- buf, err := ioutil.ReadAll(r.Body)
+ buf, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), 500)
return
diff --git a/workhorse/internal/upload/destination/objectstore/test/s3_stub.go b/workhorse/internal/upload/destination/objectstore/test/s3_stub.go
index 6b83426b852..6a6b4662904 100644
--- a/workhorse/internal/upload/destination/objectstore/test/s3_stub.go
+++ b/workhorse/internal/upload/destination/objectstore/test/s3_stub.go
@@ -1,7 +1,6 @@
package test
import (
- "io/ioutil"
"net/http/httptest"
"os"
"strings"
@@ -76,7 +75,7 @@ func S3ObjectExists(t *testing.T, sess *session.Session, config config.S3Config,
require.NoError(t, err)
require.Equal(t, int64(len(expectedBytes)), numBytes)
- output, err := ioutil.ReadFile(tmpfile.Name())
+ output, err := os.ReadFile(tmpfile.Name())
require.NoError(t, err)
require.Equal(t, []byte(expectedBytes), output)
@@ -124,13 +123,10 @@ func S3ObjectDoesNotExist(t *testing.T, sess *session.Session, config config.S3C
}
func downloadObject(t *testing.T, sess *session.Session, config config.S3Config, objectName string, handler func(tmpfile *os.File, numBytes int64, err error)) {
- tmpDir, err := ioutil.TempDir("", "workhorse-test-")
- require.NoError(t, err)
- defer os.Remove(tmpDir)
+ tmpDir := t.TempDir()
- tmpfile, err := ioutil.TempFile(tmpDir, "s3-output")
+ tmpfile, err := os.CreateTemp(tmpDir, "s3-output")
require.NoError(t, err)
- defer os.Remove(tmpfile.Name())
downloadSvc := s3manager.NewDownloader(sess)
numBytes, err := downloadSvc.Download(tmpfile, &s3.GetObjectInput{
diff --git a/workhorse/internal/upload/destination/reader_test.go b/workhorse/internal/upload/destination/reader_test.go
index a26f7746a13..40ff76d3866 100644
--- a/workhorse/internal/upload/destination/reader_test.go
+++ b/workhorse/internal/upload/destination/reader_test.go
@@ -2,7 +2,7 @@ package destination
import (
"fmt"
- "io/ioutil"
+ "io"
"strings"
"testing"
"testing/iotest"
@@ -19,7 +19,7 @@ func TestHardLimitReader(t *testing.T) {
},
)
- out, err := ioutil.ReadAll(r)
+ out, err := io.ReadAll(r)
require.NoError(t, err)
require.Equal(t, text, string(out))
}
diff --git a/workhorse/internal/upload/destination/upload_opts.go b/workhorse/internal/upload/destination/upload_opts.go
index 77a8927d34f..b2223fac912 100644
--- a/workhorse/internal/upload/destination/upload_opts.go
+++ b/workhorse/internal/upload/destination/upload_opts.go
@@ -29,8 +29,6 @@ type ObjectStorageConfig struct {
// UploadOpts represents all the options available for saving a file to object store
type UploadOpts struct {
- // TempFilePrefix is the prefix used to create temporary local file
- TempFilePrefix string
// LocalTempPath is the directory where to write a local copy of the file
LocalTempPath string
// RemoteID is the remote ObjectID provided by GitLab
diff --git a/workhorse/internal/upload/destination/upload_opts_test.go b/workhorse/internal/upload/destination/upload_opts_test.go
index 24a372495c6..fd9e56db194 100644
--- a/workhorse/internal/upload/destination/upload_opts_test.go
+++ b/workhorse/internal/upload/destination/upload_opts_test.go
@@ -283,8 +283,7 @@ func TestUseWorkhorseClientEnabled(t *testing.T) {
}
func TestGoCloudConfig(t *testing.T) {
- mux, _, cleanup := test.SetupGoCloudFileBucket(t, "azblob")
- defer cleanup()
+ mux, _ := test.SetupGoCloudFileBucket(t, "azblob")
tests := []struct {
name string
diff --git a/workhorse/internal/upload/exif.go b/workhorse/internal/upload/exif.go
new file mode 100644
index 00000000000..e77afb24502
--- /dev/null
+++ b/workhorse/internal/upload/exif.go
@@ -0,0 +1,91 @@
+package upload
+
+import (
+ "context"
+ "io"
+ "net/http"
+ "os"
+
+ "gitlab.com/gitlab-org/labkit/log"
+ "golang.org/x/image/tiff"
+
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/exif"
+)
+
+func handleExifUpload(ctx context.Context, r io.Reader, filename string, imageType exif.FileType) (io.ReadCloser, error) {
+ tmpfile, err := os.CreateTemp("", "exifremove")
+ if err != nil {
+ return nil, err
+ }
+ go func() {
+ <-ctx.Done()
+ tmpfile.Close()
+ }()
+ if err := os.Remove(tmpfile.Name()); err != nil {
+ return nil, err
+ }
+
+ _, err = io.Copy(tmpfile, r)
+ if err != nil {
+ return nil, err
+ }
+
+ if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
+ return nil, err
+ }
+
+ isValidType := false
+ switch imageType {
+ case exif.TypeJPEG:
+ isValidType = isJPEG(tmpfile)
+ case exif.TypeTIFF:
+ isValidType = isTIFF(tmpfile)
+ }
+
+ if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
+ return nil, err
+ }
+
+ if !isValidType {
+ log.WithContextFields(ctx, log.Fields{
+ "filename": filename,
+ "imageType": imageType,
+ }).Info("invalid content type, not running exiftool")
+
+ return tmpfile, nil
+ }
+
+ log.WithContextFields(ctx, log.Fields{
+ "filename": filename,
+ }).Info("running exiftool to remove any metadata")
+
+ cleaner, err := exif.NewCleaner(ctx, tmpfile)
+ if err != nil {
+ return nil, err
+ }
+
+ return cleaner, nil
+}
+
+func isTIFF(r io.Reader) bool {
+ _, err := tiff.DecodeConfig(r)
+ if err == nil {
+ return true
+ }
+
+ if _, unsupported := err.(tiff.UnsupportedError); unsupported {
+ return true
+ }
+
+ return false
+}
+
+func isJPEG(r io.Reader) bool {
+ // Only the first 512 bytes are used to sniff the content type.
+ buf, err := io.ReadAll(io.LimitReader(r, 512))
+ if err != nil {
+ return false
+ }
+
+ return http.DetectContentType(buf) == "image/jpeg"
+}
diff --git a/workhorse/internal/upload/exif/exif_test.go b/workhorse/internal/upload/exif/exif_test.go
index ee5883d9e08..75ecfc51f08 100644
--- a/workhorse/internal/upload/exif/exif_test.go
+++ b/workhorse/internal/upload/exif/exif_test.go
@@ -3,7 +3,6 @@ package exif
import (
"context"
"io"
- "io/ioutil"
"os"
"strings"
"testing"
@@ -75,7 +74,7 @@ func TestNewCleanerWithValidFile(t *testing.T) {
cleaner, err := NewCleaner(ctx, input)
require.NoError(t, err, "Expected no error when creating cleaner command")
- size, err := io.Copy(ioutil.Discard, cleaner)
+ size, err := io.Copy(io.Discard, cleaner)
require.NoError(t, err, "Expected no error when reading output")
sizeAfterStrip := int64(25399)
@@ -89,7 +88,7 @@ func TestNewCleanerWithInvalidFile(t *testing.T) {
cleaner, err := NewCleaner(ctx, strings.NewReader("invalid image"))
require.NoError(t, err, "Expected no error when creating cleaner command")
- size, err := io.Copy(ioutil.Discard, cleaner)
+ size, err := io.Copy(io.Discard, cleaner)
require.Error(t, err, "Expected error when reading output")
require.Equal(t, int64(0), size, "Size of invalid image should be 0")
}
@@ -103,7 +102,7 @@ func TestNewCleanerReadingAfterEOF(t *testing.T) {
cleaner, err := NewCleaner(ctx, input)
require.NoError(t, err, "Expected no error when creating cleaner command")
- _, err = io.Copy(ioutil.Discard, cleaner)
+ _, err = io.Copy(io.Discard, cleaner)
require.NoError(t, err, "Expected no error when reading output")
buf := make([]byte, 1)
diff --git a/workhorse/internal/upload/multipart_uploader.go b/workhorse/internal/upload/multipart_uploader.go
index 34675d2aa14..2456a2c8626 100644
--- a/workhorse/internal/upload/multipart_uploader.go
+++ b/workhorse/internal/upload/multipart_uploader.go
@@ -1,11 +1,9 @@
package upload
import (
- "fmt"
"net/http"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/api"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
)
// Multipart is a request middleware. If the request has a MIME multipart
@@ -17,12 +15,27 @@ func Multipart(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {
return rails.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) {
s := &SavedFileTracker{Request: r}
- opts, err := p.Prepare(a)
- if err != nil {
- helper.Fail500(w, r, fmt.Errorf("Multipart: error preparing file storage options"))
- return
+ interceptMultipartFiles(w, r, h, s, &eagerAuthorizer{a}, p)
+ }, "/authorize")
+}
+
+// SkipRailsPreAuthMultipart behaves like Multipart except it does not
+// pre-authorize with Rails. It is intended for use on catch-all routes
+// where we cannot pre-authorize both because we don't know which Rails
+// endpoint to call, and because eagerly pre-authorizing would add too
+// much overhead.
+func SkipRailsPreAuthMultipart(tempPath string, myAPI *api.API, h http.Handler, p Preparer) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ s := &SavedFileTracker{Request: r}
+
+ // We use testAuthorizer as a temporary measure. When
+ // https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/742 is done, we
+ // should only be using apiAuthorizer.
+ fa := &testAuthorizer{
+ test: &apiAuthorizer{myAPI},
+ actual: &eagerAuthorizer{&api.Response{TempPath: tempPath}},
}
- interceptMultipartFiles(w, r, h, a, s, opts)
- }, "/authorize")
+ interceptMultipartFiles(w, r, h, s, fa, p)
+ })
}
diff --git a/workhorse/internal/upload/rewrite.go b/workhorse/internal/upload/rewrite.go
index ff5190226af..d03445923fa 100644
--- a/workhorse/internal/upload/rewrite.go
+++ b/workhorse/internal/upload/rewrite.go
@@ -5,23 +5,19 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"mime"
"mime/multipart"
"net/http"
"net/textproto"
- "os"
"path/filepath"
"strings"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "gitlab.com/gitlab-org/labkit/log"
- "golang.org/x/image/tiff"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/api"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/lsif_transformer/parser"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/destination"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/exif"
)
@@ -62,13 +58,14 @@ var (
)
type rewriter struct {
- writer *multipart.Writer
- preauth *api.Response
+ writer *multipart.Writer
+ fileAuthorizer
+ Preparer
filter MultipartFormProcessor
finalizedFields map[string]bool
}
-func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, preauth *api.Response, filter MultipartFormProcessor, opts *destination.UploadOpts) error {
+func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, filter MultipartFormProcessor, fa fileAuthorizer, preparer Preparer) error {
// Create multipart reader
reader, err := r.MultipartReader()
if err != nil {
@@ -83,7 +80,8 @@ func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, pr
rew := &rewriter{
writer: writer,
- preauth: preauth,
+ fileAuthorizer: fa,
+ Preparer: preparer,
filter: filter,
finalizedFields: make(map[string]bool),
}
@@ -108,7 +106,7 @@ func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, pr
}
if filename != "" {
- err = rew.handleFilePart(r.Context(), name, p, opts)
+ err = rew.handleFilePart(r, name, p)
} else {
err = rew.copyPart(r.Context(), name, p)
}
@@ -128,7 +126,7 @@ func parseAndNormalizeContentDisposition(header textproto.MIMEHeader) (string, s
return params["name"], params["filename"]
}
-func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipart.Part, opts *destination.UploadOpts) error {
+func (rew *rewriter) handleFilePart(r *http.Request, name string, p *multipart.Part) error {
if rew.filter.Count() >= maxFilesAllowed {
return ErrTooManyFilesUploaded
}
@@ -141,30 +139,23 @@ func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipa
return fmt.Errorf("illegal filename: %q", filename)
}
- opts.TempFilePrefix = filename
-
- var inputReader io.ReadCloser
- var err error
-
- imageType := exif.FileTypeFromSuffix(filename)
- switch {
- case imageType != exif.TypeUnknown:
- inputReader, err = handleExifUpload(ctx, p, filename, imageType)
- if err != nil {
- return err
- }
- case rew.preauth.ProcessLsif:
- inputReader, err = handleLsifUpload(ctx, p, opts.LocalTempPath, filename, rew.preauth)
- if err != nil {
- return err
- }
- default:
- inputReader = ioutil.NopCloser(p)
+ apiResponse, err := rew.AuthorizeFile(r)
+ if err != nil {
+ return err
+ }
+ opts, err := rew.Prepare(apiResponse)
+ if err != nil {
+ return err
}
+ ctx := r.Context()
+ inputReader, err := rew.filter.TransformContents(ctx, filename, p)
+ if err != nil {
+ return err
+ }
defer inputReader.Close()
- fh, err := destination.Upload(ctx, inputReader, -1, opts)
+ fh, err := destination.Upload(ctx, inputReader, -1, filename, opts)
if err != nil {
switch err {
case destination.ErrEntityTooLarge, exif.ErrRemovingExif:
@@ -189,105 +180,63 @@ func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipa
return rew.filter.ProcessFile(ctx, name, fh, rew.writer)
}
-func handleExifUpload(ctx context.Context, r io.Reader, filename string, imageType exif.FileType) (io.ReadCloser, error) {
- tmpfile, err := ioutil.TempFile("", "exifremove")
- if err != nil {
- return nil, err
- }
- go func() {
- <-ctx.Done()
- tmpfile.Close()
- }()
- if err := os.Remove(tmpfile.Name()); err != nil {
- return nil, err
- }
-
- _, err = io.Copy(tmpfile, r)
+func (rew *rewriter) copyPart(ctx context.Context, name string, p *multipart.Part) error {
+ np, err := rew.writer.CreatePart(p.Header)
if err != nil {
- return nil, err
- }
-
- if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
- return nil, err
- }
-
- isValidType := false
- switch imageType {
- case exif.TypeJPEG:
- isValidType = isJPEG(tmpfile)
- case exif.TypeTIFF:
- isValidType = isTIFF(tmpfile)
- }
-
- if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
- return nil, err
+ return fmt.Errorf("create multipart field: %v", err)
}
- if !isValidType {
- log.WithContextFields(ctx, log.Fields{
- "filename": filename,
- "imageType": imageType,
- }).Print("invalid content type, not running exiftool")
-
- return tmpfile, nil
+ if _, err := io.Copy(np, p); err != nil {
+ return fmt.Errorf("duplicate multipart field: %v", err)
}
- log.WithContextFields(ctx, log.Fields{
- "filename": filename,
- }).Print("running exiftool to remove any metadata")
-
- cleaner, err := exif.NewCleaner(ctx, tmpfile)
- if err != nil {
- return nil, err
+ if err := rew.filter.ProcessField(ctx, name, rew.writer); err != nil {
+ return fmt.Errorf("process multipart field: %v", err)
}
- return cleaner, nil
+ return nil
}
-func isTIFF(r io.Reader) bool {
- _, err := tiff.DecodeConfig(r)
- if err == nil {
- return true
- }
+type fileAuthorizer interface {
+ AuthorizeFile(*http.Request) (*api.Response, error)
+}
- if _, unsupported := err.(tiff.UnsupportedError); unsupported {
- return true
- }
+type eagerAuthorizer struct{ response *api.Response }
- return false
+func (ea *eagerAuthorizer) AuthorizeFile(r *http.Request) (*api.Response, error) {
+ return ea.response, nil
}
-func isJPEG(r io.Reader) bool {
- // Only the first 512 bytes are used to sniff the content type.
- buf, err := ioutil.ReadAll(io.LimitReader(r, 512))
- if err != nil {
- return false
- }
+var _ fileAuthorizer = &eagerAuthorizer{}
- return http.DetectContentType(buf) == "image/jpeg"
+type apiAuthorizer struct {
+ api *api.API
}
-func handleLsifUpload(ctx context.Context, reader io.Reader, tempPath, filename string, preauth *api.Response) (io.ReadCloser, error) {
- parserConfig := parser.Config{
- TempPath: tempPath,
- }
-
- return parser.NewParser(ctx, reader, parserConfig)
+func (aa *apiAuthorizer) AuthorizeFile(r *http.Request) (*api.Response, error) {
+ return aa.api.PreAuthorizeFixedPath(
+ r,
+ "POST",
+ "/api/v4/internal/workhorse/authorize_upload",
+ )
}
-func (rew *rewriter) copyPart(ctx context.Context, name string, p *multipart.Part) error {
- np, err := rew.writer.CreatePart(p.Header)
- if err != nil {
- return fmt.Errorf("create multipart field: %v", err)
- }
+var _ fileAuthorizer = &apiAuthorizer{}
- if _, err := io.Copy(np, p); err != nil {
- return fmt.Errorf("duplicate multipart field: %v", err)
- }
+type testAuthorizer struct {
+ test fileAuthorizer
+ actual fileAuthorizer
+}
- if err := rew.filter.ProcessField(ctx, name, rew.writer); err != nil {
- return fmt.Errorf("process multipart field: %v", err)
+func (ta *testAuthorizer) AuthorizeFile(r *http.Request) (*api.Response, error) {
+ logger := log.WithRequest(r)
+ if response, err := ta.test.AuthorizeFile(r); err != nil {
+ logger.WithError(err).Error("test api preauthorize request failed")
+ } else {
+ logger.WithFields(log.Fields{
+ "temp_path": response.TempPath,
+ }).Info("test api preauthorize request")
}
- return nil
+ return ta.actual.AuthorizeFile(r)
}
diff --git a/workhorse/internal/upload/saved_file_tracker.go b/workhorse/internal/upload/saved_file_tracker.go
index b70a303a4a4..1fad5343647 100644
--- a/workhorse/internal/upload/saved_file_tracker.go
+++ b/workhorse/internal/upload/saved_file_tracker.go
@@ -3,11 +3,13 @@ package upload
import (
"context"
"fmt"
+ "io"
"mime/multipart"
"net/http"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/secret"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/destination"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/exif"
)
type SavedFileTracker struct {
@@ -44,7 +46,7 @@ func (s *SavedFileTracker) Finalize(_ context.Context) error {
return nil
}
- claims := MultipartClaims{RewrittenFields: s.rewrittenFields, StandardClaims: secret.DefaultClaims}
+ claims := MultipartClaims{RewrittenFields: s.rewrittenFields, RegisteredClaims: secret.DefaultClaims}
tokenString, err := secret.JWTTokenString(claims)
if err != nil {
return fmt.Errorf("savedFileTracker.Finalize: %v", err)
@@ -54,6 +56,12 @@ func (s *SavedFileTracker) Finalize(_ context.Context) error {
return nil
}
-func (s *SavedFileTracker) Name() string {
- return "accelerate"
+func (s *SavedFileTracker) Name() string { return "accelerate" }
+
+func (*SavedFileTracker) TransformContents(ctx context.Context, filename string, r io.Reader) (io.ReadCloser, error) {
+ if imageType := exif.FileTypeFromSuffix(filename); imageType != exif.TypeUnknown {
+ return handleExifUpload(ctx, r, filename, imageType)
+ }
+
+ return io.NopCloser(r), nil
}
diff --git a/workhorse/internal/upload/skip_rails_authorizer.go b/workhorse/internal/upload/skip_rails_authorizer.go
deleted file mode 100644
index e74048fb6e3..00000000000
--- a/workhorse/internal/upload/skip_rails_authorizer.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package upload
-
-import (
- "net/http"
-
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/api"
-)
-
-// SkipRailsAuthorizer implements a fake PreAuthorizer that does not call
-// the gitlab-rails API. It must be fast because it gets called on each
-// request proxied to Rails.
-type SkipRailsAuthorizer struct {
- // TempPath is a directory where workhorse can store files that can later
- // be accessed by gitlab-rails.
- TempPath string
-}
-
-func (l *SkipRailsAuthorizer) PreAuthorizeHandler(next api.HandleFunc, _ string) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- next(w, r, &api.Response{TempPath: l.TempPath})
- })
-}
diff --git a/workhorse/internal/upload/uploads.go b/workhorse/internal/upload/uploads.go
index 8272a3d920d..61b419901a7 100644
--- a/workhorse/internal/upload/uploads.go
+++ b/workhorse/internal/upload/uploads.go
@@ -4,7 +4,7 @@ import (
"bytes"
"context"
"fmt"
- "io/ioutil"
+ "io"
"mime/multipart"
"net/http"
@@ -25,7 +25,7 @@ type PreAuthorizer interface {
type MultipartClaims struct {
RewrittenFields map[string]string `json:"rewritten_fields"`
- jwt.StandardClaims
+ jwt.RegisteredClaims
}
// MultipartFormProcessor abstracts away implementation differences
@@ -36,17 +36,18 @@ type MultipartFormProcessor interface {
Finalize(ctx context.Context) error
Name() string
Count() int
+ TransformContents(ctx context.Context, filename string, r io.Reader) (io.ReadCloser, error)
}
// interceptMultipartFiles is the core of the implementation of
// Multipart.
-func interceptMultipartFiles(w http.ResponseWriter, r *http.Request, h http.Handler, preauth *api.Response, filter MultipartFormProcessor, opts *destination.UploadOpts) {
+func interceptMultipartFiles(w http.ResponseWriter, r *http.Request, h http.Handler, filter MultipartFormProcessor, fa fileAuthorizer, p Preparer) {
var body bytes.Buffer
writer := multipart.NewWriter(&body)
defer writer.Close()
// Rewrite multipart form data
- err := rewriteFormFilesFromMultipart(r, writer, preauth, filter, opts)
+ err := rewriteFormFilesFromMultipart(r, writer, filter, fa, p)
if err != nil {
switch err {
case ErrInjectedClientParam:
@@ -71,7 +72,7 @@ func interceptMultipartFiles(w http.ResponseWriter, r *http.Request, h http.Hand
writer.Close()
// Hijack the request
- r.Body = ioutil.NopCloser(&body)
+ r.Body = io.NopCloser(&body)
r.ContentLength = int64(body.Len())
r.Header.Set("Content-Type", writer.FormDataContentType())
diff --git a/workhorse/internal/upload/uploads_test.go b/workhorse/internal/upload/uploads_test.go
index a9c8834d4be..ffe9fec302e 100644
--- a/workhorse/internal/upload/uploads_test.go
+++ b/workhorse/internal/upload/uploads_test.go
@@ -6,12 +6,12 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
"mime/multipart"
"net/http"
"net/http/httptest"
"net/textproto"
"os"
+ "path"
"regexp"
"strconv"
"strings"
@@ -54,7 +54,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) {
ts := testhelper.TestServerWithHandler(regexp.MustCompile(`/url/path\z`), func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "PATCH", r.Method, "method")
- body, err := ioutil.ReadAll(r.Body)
+ body, err := io.ReadAll(r.Body)
require.NoError(t, err)
require.Equal(t, "REQUEST", string(body), "request body")
@@ -66,19 +66,14 @@ func TestUploadHandlerForwardingRawData(t *testing.T) {
httpRequest, err := http.NewRequest("PATCH", ts.URL+"/url/path", bytes.NewBufferString("REQUEST"))
require.NoError(t, err)
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
-
+ tempPath := t.TempDir()
response := httptest.NewRecorder()
handler := newProxy(ts.URL)
- apiResponse := &api.Response{TempPath: tempPath}
+ fa := &eagerAuthorizer{&api.Response{TempPath: tempPath}}
preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
- interceptMultipartFiles(response, httpRequest, handler, apiResponse, nil, opts)
+ interceptMultipartFiles(response, httpRequest, handler, nil, fa, preparer)
require.Equal(t, 202, response.Code)
require.Equal(t, "RESPONSE", response.Body.String(), "response body")
@@ -86,10 +81,7 @@ func TestUploadHandlerForwardingRawData(t *testing.T) {
func TestUploadHandlerRewritingMultiPartData(t *testing.T) {
var filePath string
-
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
+ tempPath := t.TempDir()
ts := testhelper.TestServerWithHandler(regexp.MustCompile(`/url/path\z`), func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "PUT", r.Method, "method")
@@ -137,19 +129,17 @@ func TestUploadHandlerRewritingMultiPartData(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
httpRequest = httpRequest.WithContext(ctx)
- httpRequest.Body = ioutil.NopCloser(&buffer)
+ httpRequest.Body = io.NopCloser(&buffer)
httpRequest.ContentLength = int64(buffer.Len())
httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
handler := newProxy(ts.URL)
- apiResponse := &api.Response{TempPath: tempPath}
+ fa := &eagerAuthorizer{&api.Response{TempPath: tempPath}}
preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
- interceptMultipartFiles(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
+ interceptMultipartFiles(response, httpRequest, handler, &testFormProcessor{}, fa, preparer)
require.Equal(t, 202, response.Code)
cancel() // this will trigger an async cleanup
@@ -159,10 +149,6 @@ func TestUploadHandlerRewritingMultiPartData(t *testing.T) {
func TestUploadHandlerDetectingInjectedMultiPartData(t *testing.T) {
var filePath string
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
-
tests := []struct {
name string
field string
@@ -213,12 +199,8 @@ func TestUploadHandlerDetectingInjectedMultiPartData(t *testing.T) {
response := httptest.NewRecorder()
handler := newProxy(ts.URL)
- apiResponse := &api.Response{TempPath: tempPath}
- preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
- interceptMultipartFiles(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
+ testInterceptMultipartFiles(t, response, httpRequest, handler, &testFormProcessor{})
require.Equal(t, test.response, response.Code)
cancel() // this will trigger an async cleanup
@@ -228,10 +210,6 @@ func TestUploadHandlerDetectingInjectedMultiPartData(t *testing.T) {
}
func TestUploadProcessingField(t *testing.T) {
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
-
var buffer bytes.Buffer
writer := multipart.NewWriter(&buffer)
@@ -243,12 +221,8 @@ func TestUploadProcessingField(t *testing.T) {
httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
- apiResponse := &api.Response{TempPath: tempPath}
- preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
- interceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
+ testInterceptMultipartFiles(t, response, httpRequest, nilHandler, &testFormProcessor{})
require.Equal(t, 500, response.Code)
}
@@ -256,15 +230,11 @@ func TestUploadProcessingField(t *testing.T) {
func TestUploadingMultipleFiles(t *testing.T) {
testhelper.ConfigureSecret()
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
-
var buffer bytes.Buffer
writer := multipart.NewWriter(&buffer)
for i := 0; i < 11; i++ {
- _, err = writer.CreateFormFile(fmt.Sprintf("file %v", i), "my.file")
+ _, err := writer.CreateFormFile(fmt.Sprintf("file %v", i), "my.file")
require.NoError(t, err)
}
require.NoError(t, writer.Close())
@@ -274,23 +244,18 @@ func TestUploadingMultipleFiles(t *testing.T) {
httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
- apiResponse := &api.Response{TempPath: tempPath}
- preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
- interceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
+ testInterceptMultipartFiles(t, response, httpRequest, nilHandler, &testFormProcessor{})
require.Equal(t, 400, response.Code)
require.Equal(t, "upload request contains more than 10 files\n", response.Body.String())
}
func TestUploadProcessingFile(t *testing.T) {
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
+ testhelper.ConfigureSecret()
+ tempPath := t.TempDir()
- _, testServer := test.StartObjectStore()
+ objectStore, testServer := test.StartObjectStore()
defer testServer.Close()
storeUrl := testServer.URL + test.ObjectPath
@@ -298,21 +263,24 @@ func TestUploadProcessingFile(t *testing.T) {
tests := []struct {
name string
preauth *api.Response
+ content func(t *testing.T) []byte
}{
{
name: "FileStore Upload",
preauth: &api.Response{TempPath: tempPath},
+ content: func(t *testing.T) []byte {
+ entries, err := os.ReadDir(tempPath)
+ require.NoError(t, err)
+ require.Len(t, entries, 1)
+ content, err := os.ReadFile(path.Join(tempPath, entries[0].Name()))
+ require.NoError(t, err)
+ return content
+ },
},
{
name: "ObjectStore Upload",
- preauth: &api.Response{RemoteObject: api.RemoteObject{StoreURL: storeUrl}},
- },
- {
- name: "ObjectStore and FileStore Upload",
- preauth: &api.Response{
- TempPath: tempPath,
- RemoteObject: api.RemoteObject{StoreURL: storeUrl},
- },
+ preauth: &api.Response{RemoteObject: api.RemoteObject{StoreURL: storeUrl, ID: "123"}},
+ content: func(*testing.T) []byte { return objectStore.GetObject(test.ObjectPath) },
},
}
@@ -330,26 +298,20 @@ func TestUploadProcessingFile(t *testing.T) {
httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
- apiResponse := &api.Response{TempPath: tempPath}
+ fa := &eagerAuthorizer{test.preauth}
preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
- interceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
+ interceptMultipartFiles(response, httpRequest, nilHandler, &testFormProcessor{}, fa, preparer)
require.Equal(t, 200, response.Code)
+ require.Equal(t, "test", string(test.content(t)))
})
}
-
}
func TestInvalidFileNames(t *testing.T) {
testhelper.ConfigureSecret()
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
-
for _, testCase := range []struct {
filename string
code int
@@ -376,24 +338,14 @@ func TestInvalidFileNames(t *testing.T) {
httpRequest.Header.Set("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
- apiResponse := &api.Response{TempPath: tempPath}
- preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
-
- interceptMultipartFiles(response, httpRequest, nilHandler, apiResponse, &SavedFileTracker{Request: httpRequest}, opts)
+ testInterceptMultipartFiles(t, response, httpRequest, nilHandler, &SavedFileTracker{Request: httpRequest})
require.Equal(t, testCase.code, response.Code)
- require.Equal(t, testCase.expectedPrefix, opts.TempFilePrefix)
}
}
func TestContentDispositionRewrite(t *testing.T) {
testhelper.ConfigureSecret()
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
-
tests := []struct {
desc string
header string
@@ -442,12 +394,7 @@ func TestContentDispositionRewrite(t *testing.T) {
})
response := httptest.NewRecorder()
- apiResponse := &api.Response{TempPath: tempPath}
- preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
-
- interceptMultipartFiles(response, httpRequest, customHandler, apiResponse, &SavedFileTracker{Request: httpRequest}, opts)
+ testInterceptMultipartFiles(t, response, httpRequest, customHandler, &SavedFileTracker{Request: httpRequest})
upstreamRequest, err := http.ReadRequest(bufio.NewReader(&upstreamRequestBuffer))
require.NoError(t, err)
@@ -471,7 +418,7 @@ func TestContentDispositionRewrite(t *testing.T) {
}
func TestUploadHandlerRemovingExif(t *testing.T) {
- content, err := ioutil.ReadFile("exif/testdata/sample_exif.jpg")
+ content, err := os.ReadFile("exif/testdata/sample_exif.jpg")
require.NoError(t, err)
runUploadTest(t, content, "sample_exif.jpg", 200, func(w http.ResponseWriter, r *http.Request) {
@@ -489,7 +436,7 @@ func TestUploadHandlerRemovingExif(t *testing.T) {
}
func TestUploadHandlerRemovingExifTiff(t *testing.T) {
- content, err := ioutil.ReadFile("exif/testdata/sample_exif.tiff")
+ content, err := os.ReadFile("exif/testdata/sample_exif.tiff")
require.NoError(t, err)
runUploadTest(t, content, "sample_exif.tiff", 200, func(w http.ResponseWriter, r *http.Request) {
@@ -507,14 +454,14 @@ func TestUploadHandlerRemovingExifTiff(t *testing.T) {
}
func TestUploadHandlerRemovingExifInvalidContentType(t *testing.T) {
- content, err := ioutil.ReadFile("exif/testdata/sample_exif_invalid.jpg")
+ content, err := os.ReadFile("exif/testdata/sample_exif_invalid.jpg")
require.NoError(t, err)
runUploadTest(t, content, "sample_exif_invalid.jpg", 200, func(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(100000)
require.NoError(t, err)
- output, err := ioutil.ReadFile(r.FormValue("file.path"))
+ output, err := os.ReadFile(r.FormValue("file.path"))
require.NoError(t, err)
require.Equal(t, content, output, "Expected the file to be same as before")
@@ -524,7 +471,7 @@ func TestUploadHandlerRemovingExifInvalidContentType(t *testing.T) {
}
func TestUploadHandlerRemovingExifCorruptedFile(t *testing.T) {
- content, err := ioutil.ReadFile("exif/testdata/sample_exif_corrupted.jpg")
+ content, err := os.ReadFile("exif/testdata/sample_exif_corrupted.jpg")
require.NoError(t, err)
runUploadTest(t, content, "sample_exif_corrupted.jpg", 422, func(w http.ResponseWriter, r *http.Request) {
@@ -534,10 +481,6 @@ func TestUploadHandlerRemovingExifCorruptedFile(t *testing.T) {
}
func runUploadTest(t *testing.T, image []byte, filename string, httpCode int, tsHandler func(http.ResponseWriter, *http.Request)) {
- tempPath, err := ioutil.TempDir("", "uploads")
- require.NoError(t, err)
- defer os.RemoveAll(tempPath)
-
var buffer bytes.Buffer
writer := multipart.NewWriter(&buffer)
@@ -565,12 +508,8 @@ func runUploadTest(t *testing.T, image []byte, filename string, httpCode int, ts
response := httptest.NewRecorder()
handler := newProxy(ts.URL)
- apiResponse := &api.Response{TempPath: tempPath}
- preparer := &DefaultPreparer{}
- opts, err := preparer.Prepare(apiResponse)
- require.NoError(t, err)
- interceptMultipartFiles(response, httpRequest, handler, apiResponse, &testFormProcessor{}, opts)
+ testInterceptMultipartFiles(t, response, httpRequest, handler, &testFormProcessor{})
require.Equal(t, httpCode, response.Code)
}
@@ -587,3 +526,12 @@ func waitUntilDeleted(t *testing.T, path string) {
}, 10*time.Second, 10*time.Millisecond)
require.True(t, os.IsNotExist(err), "expected the file to be deleted")
}
+
+func testInterceptMultipartFiles(t *testing.T, w http.ResponseWriter, r *http.Request, h http.Handler, filter MultipartFormProcessor) {
+ t.Helper()
+
+ fa := &eagerAuthorizer{&api.Response{TempPath: t.TempDir()}}
+ preparer := &DefaultPreparer{}
+
+ interceptMultipartFiles(w, r, h, filter, fa, preparer)
+}
diff --git a/workhorse/internal/upstream/handlers_test.go b/workhorse/internal/upstream/handlers_test.go
index 10c7479f5c5..03ca80ddcb9 100644
--- a/workhorse/internal/upstream/handlers_test.go
+++ b/workhorse/internal/upstream/handlers_test.go
@@ -4,7 +4,7 @@ import (
"bytes"
"compress/gzip"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"testing"
@@ -20,7 +20,7 @@ func TestGzipEncoding(t *testing.T) {
fmt.Fprint(w, "test")
w.Close()
- body := ioutil.NopCloser(&b)
+ body := io.NopCloser(&b)
req, err := http.NewRequest("POST", "http://address/test", body)
require.NoError(t, err)
@@ -38,7 +38,7 @@ func TestNoEncoding(t *testing.T) {
resp := httptest.NewRecorder()
var b bytes.Buffer
- body := ioutil.NopCloser(&b)
+ body := io.NopCloser(&b)
req, err := http.NewRequest("POST", "http://address/test", body)
require.NoError(t, err)
diff --git a/workhorse/internal/upstream/roundtripper/roundtripper_test.go b/workhorse/internal/upstream/roundtripper/roundtripper_test.go
index eed71cc5bae..d3cec80d49b 100644
--- a/workhorse/internal/upstream/roundtripper/roundtripper_test.go
+++ b/workhorse/internal/upstream/roundtripper/roundtripper_test.go
@@ -4,7 +4,7 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/http/httptest"
"net/url"
@@ -86,7 +86,7 @@ func testNewBackendRoundTripper(t *testing.T, ts *httptest.Server, tlsClientConf
require.NoError(t, err, "perform roundtrip")
defer response.Body.Close()
- body, err := ioutil.ReadAll(response.Body)
+ body, err := io.ReadAll(response.Body)
require.NoError(t, err)
require.Equal(t, expectedResponseBody, string(body))
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index dd106053f8b..95c9b99b833 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -223,7 +223,7 @@ func configureRoutes(u *upstream) {
mimeMultipartUploader := upload.Multipart(api, signingProxy, preparer)
uploadPath := path.Join(u.DocumentRoot, "uploads/tmp")
- tempfileMultipartProxy := upload.Multipart(&upload.SkipRailsAuthorizer{TempPath: uploadPath}, proxy, preparer)
+ tempfileMultipartProxy := upload.SkipRailsPreAuthMultipart(uploadPath, api, proxy, preparer)
ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", tempfileMultipartProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout)
ciAPILongPolling := builds.RegisterHandler(ciAPIProxyQueue, redis.WatchKey, u.APICILongPollingDuration)
diff --git a/workhorse/internal/upstream/upstream_test.go b/workhorse/internal/upstream/upstream_test.go
index 8f054f5ccef..f931c1b31b3 100644
--- a/workhorse/internal/upstream/upstream_test.go
+++ b/workhorse/internal/upstream/upstream_test.go
@@ -3,7 +3,6 @@ package upstream
import (
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"os"
@@ -287,7 +286,7 @@ func runTestCases(t *testing.T, ws *httptest.Server, testCases []testCase) {
require.NoError(t, err)
defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode, "response code")
diff --git a/workhorse/internal/utils/svg/README.md b/workhorse/internal/utils/svg/README.md
index e5531f47473..4057316927c 100644
--- a/workhorse/internal/utils/svg/README.md
+++ b/workhorse/internal/utils/svg/README.md
@@ -15,13 +15,13 @@ package main
import (
"fmt"
- "io/ioutil"
+ "os"
svg "github.com/h2non/go-is-svg"
)
func main() {
- buf, err := ioutil.ReadFile("_example/example.svg")
+ buf, err := os.ReadFile("_example/example.svg")
if err != nil {
fmt.Printf("Error: %s\n", err)
return
diff --git a/workhorse/internal/zipartifacts/metadata_test.go b/workhorse/internal/zipartifacts/metadata_test.go
index 353ed4376f6..e4799ba4a59 100644
--- a/workhorse/internal/zipartifacts/metadata_test.go
+++ b/workhorse/internal/zipartifacts/metadata_test.go
@@ -6,7 +6,6 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
"os"
"testing"
@@ -41,7 +40,7 @@ func validateMetadata(r io.Reader) error {
return err
}
- meta, err := ioutil.ReadAll(gz)
+ meta, err := io.ReadAll(gz)
if err != nil {
return err
}
@@ -59,7 +58,7 @@ func validateMetadata(r io.Reader) error {
func TestGenerateZipMetadataFromFile(t *testing.T) {
var metaBuffer bytes.Buffer
- f, err := ioutil.TempFile("", "workhorse-metadata.zip-")
+ f, err := os.CreateTemp("", "workhorse-metadata.zip-")
if f != nil {
defer os.Remove(f.Name())
}
@@ -84,7 +83,7 @@ func TestGenerateZipMetadataFromFile(t *testing.T) {
}
func TestErrNotAZip(t *testing.T) {
- f, err := ioutil.TempFile("", "workhorse-metadata.zip-")
+ f, err := os.CreateTemp("", "workhorse-metadata.zip-")
if f != nil {
defer os.Remove(f.Name())
}
diff --git a/workhorse/logging.go b/workhorse/logging.go
index 69718e6e834..e2e603b15e8 100644
--- a/workhorse/logging.go
+++ b/workhorse/logging.go
@@ -3,7 +3,6 @@ package main
import (
"fmt"
"io"
- "io/ioutil"
goLog "log"
"os"
@@ -28,7 +27,7 @@ func startLogging(file string, format string) (io.Closer, error) {
switch format {
case noneLogType:
- return logkit.Initialize(logkit.WithWriter(ioutil.Discard))
+ return logkit.Initialize(logkit.WithWriter(io.Discard))
case jsonLogFormat:
return logkit.Initialize(
logkit.WithOutputName(file),
@@ -53,7 +52,7 @@ func startLogging(file string, format string) (io.Closer, error) {
// In text format, we use a separate logger for access logs
func getAccessLogger(file string, format string) (*log.Logger, io.Closer, error) {
if format != "text" {
- return log.StandardLogger(), ioutil.NopCloser(nil), nil
+ return log.StandardLogger(), io.NopCloser(nil), nil
}
if file == "" {
diff --git a/workhorse/main.go b/workhorse/main.go
index 55c29b8abf5..91008e16961 100644
--- a/workhorse/main.go
+++ b/workhorse/main.go
@@ -4,7 +4,6 @@ import (
"context"
"flag"
"fmt"
- "io/ioutil"
"net"
"net/http"
_ "net/http/pprof"
@@ -137,7 +136,7 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error
tomlData := ""
if *configFile != "" {
- buf, err := ioutil.ReadFile(*configFile)
+ buf, err := os.ReadFile(*configFile)
if err != nil {
return nil, nil, fmt.Errorf("configFile: %v", err)
}
@@ -149,6 +148,14 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error
return nil, nil, fmt.Errorf("configFile: %v", err)
}
+ cfg.MetricsListener = cfgFromFile.MetricsListener
+ if boot.prometheusListenAddr != "" {
+ if cfg.MetricsListener != nil {
+ return nil, nil, fmt.Errorf("configFile: both prometheusListenAddr and metrics_listener can't be specified")
+ }
+ cfg.MetricsListener = &config.ListenerConfig{Network: "tcp", Addr: boot.prometheusListenAddr}
+ }
+
cfg.Redis = cfgFromFile.Redis
cfg.ObjectStorageCredentials = cfgFromFile.ObjectStorageCredentials
cfg.ImageResizerConfig = cfgFromFile.ImageResizerConfig
@@ -196,11 +203,10 @@ func run(boot bootConfig, cfg config.Config) error {
}
monitoringOpts := []monitoring.Option{monitoring.WithBuildInformation(Version, BuildTime)}
-
- if boot.prometheusListenAddr != "" {
- l, err := net.Listen("tcp", boot.prometheusListenAddr)
+ if cfg.MetricsListener != nil {
+ l, err := newListener("metrics", *cfg.MetricsListener)
if err != nil {
- return fmt.Errorf("prometheusListenAddr: %v", err)
+ return err
}
monitoringOpts = append(monitoringOpts, monitoring.WithListener(l))
}
diff --git a/workhorse/main_test.go b/workhorse/main_test.go
index 59090cc1232..b6a09efa8db 100644
--- a/workhorse/main_test.go
+++ b/workhorse/main_test.go
@@ -8,7 +8,6 @@ import (
"fmt"
"image/png"
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
@@ -307,7 +306,7 @@ func TestGzipAssets(t *testing.T) {
resp, err := http.DefaultTransport.RoundTrip(req)
require.NoError(t, err, desc)
defer resp.Body.Close()
- b, err := ioutil.ReadAll(resp.Body)
+ b, err := io.ReadAll(resp.Body)
require.NoError(t, err, desc)
require.Equal(t, 200, resp.StatusCode, "%s: status code", desc)
@@ -366,7 +365,7 @@ func TestAltDocumentAssets(t *testing.T) {
resp, err := http.DefaultTransport.RoundTrip(req)
require.NoError(t, err)
defer resp.Body.Close()
- b, err := ioutil.ReadAll(resp.Body)
+ b, err := io.ReadAll(resp.Body)
require.NoError(t, err)
if tc.content != "" {
@@ -412,7 +411,7 @@ func doSendDataRequest(path string, command, literalJSON string) (*http.Response
}
defer resp.Body.Close()
- bodyData, err := ioutil.ReadAll(resp.Body)
+ bodyData, err := io.ReadAll(resp.Body)
if err != nil {
return resp, nil, err
}
@@ -574,7 +573,7 @@ func TestAPIFalsePositivesAreProxied(t *testing.T) {
require.NoError(t, err, "%s %q", tc.method, tc.path)
defer resp.Body.Close()
- respBody, err := ioutil.ReadAll(resp.Body)
+ respBody, err := io.ReadAll(resp.Body)
require.NoError(t, err, "%s %q: reading body", tc.method, tc.path)
require.Equal(t, 200, resp.StatusCode, "%s %q: status code", tc.method, tc.path)
@@ -833,7 +832,7 @@ func httpGet(t *testing.T, url string, headers map[string]string) (*http.Respons
require.NoError(t, err)
defer resp.Body.Close()
- b, err := ioutil.ReadAll(resp.Body)
+ b, err := io.ReadAll(resp.Body)
require.NoError(t, err)
return resp, string(b)
diff --git a/workhorse/proxy_test.go b/workhorse/proxy_test.go
index 02148c07522..6dd1354e618 100644
--- a/workhorse/proxy_test.go
+++ b/workhorse/proxy_test.go
@@ -3,7 +3,7 @@ package main
import (
"bytes"
"fmt"
- "io/ioutil"
+ "io"
"net"
"net/http"
"net/http/httptest"
@@ -51,7 +51,7 @@ func TestProxyRequest(t *testing.T) {
"expect Gitlab-Workhorse-Proxy-Start to start with 1",
)
- body, err := ioutil.ReadAll(r.Body)
+ body, err := io.ReadAll(r.Body)
require.NoError(t, err, "read body")
require.Equal(t, "REQUEST", string(body), "body contents")
diff --git a/workhorse/sendfile_test.go b/workhorse/sendfile_test.go
index 0a01e410d39..f2b6da4eebd 100644
--- a/workhorse/sendfile_test.go
+++ b/workhorse/sendfile_test.go
@@ -2,7 +2,7 @@ package main
import (
"fmt"
- "io/ioutil"
+ "io"
"mime"
"net/http"
"os"
@@ -53,14 +53,14 @@ func allowedXSendfileDownload(t *testing.T, contentFilename string, filePath str
require.NoError(t, os.MkdirAll(cacheDir, 0755))
contentBytes := []byte("content")
- require.NoError(t, ioutil.WriteFile(contentPath, contentBytes, 0644))
+ require.NoError(t, os.WriteFile(contentPath, contentBytes, 0644))
resp, err := http.Get(fmt.Sprintf("%s/%s", ws.URL, filePath))
require.NoError(t, err)
requireAttachmentName(t, resp, contentFilename)
- actual, err := ioutil.ReadAll(resp.Body)
+ actual, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.NoError(t, resp.Body.Close())
@@ -89,7 +89,7 @@ func deniedXSendfileDownload(t *testing.T, contentFilename string, filePath stri
requireAttachmentName(t, resp, contentFilename)
- actual, err := ioutil.ReadAll(resp.Body)
+ actual, err := io.ReadAll(resp.Body)
require.NoError(t, err, "read body")
require.NoError(t, resp.Body.Close())
diff --git a/workhorse/upload_test.go b/workhorse/upload_test.go
index 180598ab260..dedda4ea655 100644
--- a/workhorse/upload_test.go
+++ b/workhorse/upload_test.go
@@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"mime/multipart"
"net/http"
"net/http/httptest"
@@ -68,7 +67,7 @@ func expectSignedRequest(t *testing.T, r *http.Request) {
func uploadTestServer(t *testing.T, authorizeTests func(r *http.Request), extraTests func(r *http.Request)) *httptest.Server {
return testhelper.TestServerWithHandler(regexp.MustCompile(`.`), func(w http.ResponseWriter, r *http.Request) {
- if strings.HasSuffix(r.URL.Path, "/authorize") {
+ if strings.HasSuffix(r.URL.Path, "/authorize") || r.URL.Path == "/api/v4/internal/workhorse/authorize_upload" {
expectSignedRequest(t, r)
w.Header().Set("Content-Type", api.ResponseContentType)
@@ -154,6 +153,10 @@ func TestAcceleratedUpload(t *testing.T) {
t.Run(tt.resource, func(t *testing.T) {
ts := uploadTestServer(t,
func(r *http.Request) {
+ if r.URL.Path == "/api/v4/internal/workhorse/authorize_upload" {
+ // Nothing to validate: this is a hard coded URL
+ return
+ }
resource := strings.TrimRight(tt.resource, "/")
// Validate %2F characters haven't been unescaped
require.Equal(t, resource+"/authorize", r.URL.String())
@@ -270,24 +273,23 @@ func TestUnacceleratedUploads(t *testing.T) {
func TestBlockingRewrittenFieldsHeader(t *testing.T) {
canary := "untrusted header passed by user"
+ multiPartBody, multiPartContentType, err := multipartBodyWithFile()
+ require.NoError(t, err)
+
testCases := []struct {
desc string
contentType string
body io.Reader
present bool
}{
- {"multipart with file", "", nil, true}, // placeholder
+ {"multipart with file", multiPartContentType, multiPartBody, true},
{"no multipart", "text/plain", nil, false},
}
- var err error
- testCases[0].body, testCases[0].contentType, err = multipartBodyWithFile()
- require.NoError(t, err)
-
for _, tc := range testCases {
ts := testhelper.TestServerWithHandler(regexp.MustCompile(`.`), func(w http.ResponseWriter, r *http.Request) {
key := upload.RewrittenFieldsHeader
- if tc.present {
+ if tc.present && r.URL.Path != "/api/v4/internal/workhorse/authorize_upload" {
require.Contains(t, r.Header, key)
} else {
require.NotContains(t, r.Header, key)
@@ -342,7 +344,7 @@ func TestLfsUpload(t *testing.T) {
require.Equal(t, oid, r.Form.Get("file.sha256"), "Invalid SHA256 populated")
require.Equal(t, strconv.Itoa(len(reqBody)), r.Form.Get("file.size"), "Invalid size populated")
- tempfile, err := ioutil.ReadFile(r.Form.Get("file.path"))
+ tempfile, err := os.ReadFile(r.Form.Get("file.path"))
require.NoError(t, err)
require.Equal(t, reqBody, string(tempfile), "Temporary file has the wrong body")
@@ -366,7 +368,7 @@ func TestLfsUpload(t *testing.T) {
require.NoError(t, err)
defer resp.Body.Close()
- rspData, err := ioutil.ReadAll(resp.Body)
+ rspData, err := io.ReadAll(resp.Body)
require.NoError(t, err)
// Expect the (eventual) response to be proxied through, untouched
@@ -428,7 +430,7 @@ func TestLfsUploadRouting(t *testing.T) {
require.NoError(t, err)
defer resp.Body.Close()
- rspData, err := ioutil.ReadAll(resp.Body)
+ rspData, err := io.ReadAll(resp.Body)
require.NoError(t, err)
if tc.match {
@@ -467,7 +469,7 @@ func packageUploadTestServer(t *testing.T, method string, resource string, reqBo
require.Equal(t, len, r.Form.Get("file.size"), "Invalid size populated")
tmpFilePath := r.Form.Get("file.path")
- fileData, err := ioutil.ReadFile(tmpFilePath)
+ fileData, err := os.ReadFile(tmpFilePath)
defer os.Remove(tmpFilePath)
require.NoError(t, err)
@@ -496,7 +498,7 @@ func testPackageFileUpload(t *testing.T, method string, resource string) {
resp, err := http.DefaultClient.Do(req)
require.NoError(t, err)
- respData, err := ioutil.ReadAll(resp.Body)
+ respData, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, rspBody, string(respData), "Temporary file has the wrong body")
defer resp.Body.Close()