diff --git a/workhorse/internal/api/api.go b/workhorse/internal/api/api.go index aa6d7cf1bc785cf78ae8677f96edc8dc16b779c0..6a6a51b27bbd0c56b685ca6531dd539fa1a1fee8 100644 --- a/workhorse/internal/api/api.go +++ b/workhorse/internal/api/api.go @@ -19,7 +19,6 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/config" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" "gitlab.com/gitlab-org/gitlab/workhorse/internal/log" - "gitlab.com/gitlab-org/gitlab/workhorse/internal/secret" ) diff --git a/workhorse/internal/dependencyproxy/dependencyproxy.go b/workhorse/internal/dependencyproxy/dependencyproxy.go index 90f3042a342c452fa7a3dbbcbf1fbe406103a025..6651b5aee8417a66ee21383b7c82b4a817096c9b 100644 --- a/workhorse/internal/dependencyproxy/dependencyproxy.go +++ b/workhorse/internal/dependencyproxy/dependencyproxy.go @@ -9,12 +9,12 @@ import ( "gitlab.com/gitlab-org/labkit/log" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" - "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport" "gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport" ) var httpClient = &http.Client{ - Transport: httptransport.New(), + Transport: transport.NewRestrictedTransport(), } type Injector struct { diff --git a/workhorse/internal/helper/httptransport/http_transport.go b/workhorse/internal/helper/httptransport/http_transport.go deleted file mode 100644 index c7c3c5283f5d019a175a0862cdb5e5355f2e621f..0000000000000000000000000000000000000000 --- a/workhorse/internal/helper/httptransport/http_transport.go +++ /dev/null @@ -1,37 +0,0 @@ -package httptransport - -import ( - "net/http" - "time" - - "gitlab.com/gitlab-org/labkit/correlation" - "gitlab.com/gitlab-org/labkit/tracing" -) - -type Option func(*http.Transport) - -// Defines a http.Transport with values -// that are more restrictive than for http.DefaultTransport, -// they define shorter TLS Handshake, and more aggressive connection closing -// to prevent the connection hanging and reduce FD usage -func New(options ...Option) http.RoundTripper { - t := http.DefaultTransport.(*http.Transport).Clone() - - // To avoid keep around TCP connections to http servers we're done with - t.MaxIdleConns = 2 - - // A stricter timeout for fetching from external sources that can be slow - t.ResponseHeaderTimeout = 30 * time.Second - - for _, option := range options { - option(t) - } - - return tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(t)) -} - -func WithDisabledCompression() Option { - return func(t *http.Transport) { - t.DisableCompression = true - } -} diff --git a/workhorse/internal/imageresizer/image_resizer.go b/workhorse/internal/imageresizer/image_resizer.go index 8c3271b6f11badac20b56dfcf97227ac97a86aba..092369cd2af8be2c256946ef4be0832398c6687a 100644 --- a/workhorse/internal/imageresizer/image_resizer.go +++ b/workhorse/internal/imageresizer/image_resizer.go @@ -21,9 +21,9 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/config" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" - "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport" "gitlab.com/gitlab-org/gitlab/workhorse/internal/log" "gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport" ) type Resizer struct { @@ -69,7 +69,7 @@ const ( var envInjector = tracing.NewEnvInjector() var httpClient = &http.Client{ - Transport: httptransport.New(), + Transport: transport.NewRestrictedTransport(), } const ( diff --git a/workhorse/internal/sendurl/sendurl.go b/workhorse/internal/sendurl/sendurl.go index 205ec8a0e9fbb09956e7e3f0e6c5940612329063..8e679c6b47524a39eb991c7af69133e7fb6a3af6 100644 --- a/workhorse/internal/sendurl/sendurl.go +++ b/workhorse/internal/sendurl/sendurl.go @@ -11,9 +11,9 @@ import ( "gitlab.com/gitlab-org/labkit/mask" "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper" - "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport" "gitlab.com/gitlab-org/gitlab/workhorse/internal/log" "gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport" ) type entry struct{ senddata.Prefix } @@ -44,7 +44,7 @@ var preserveHeaderKeys = map[string]bool{ "Pragma": true, // Support for HTTP 1.0 proxies } -var httpTransport = httptransport.New() +var httpTransport = transport.NewRestrictedTransport() var httpClient = &http.Client{ Transport: httpTransport, diff --git a/workhorse/internal/transport/transport.go b/workhorse/internal/transport/transport.go new file mode 100644 index 0000000000000000000000000000000000000000..f19d332a28a63263378944fded2358d5106b8f2f --- /dev/null +++ b/workhorse/internal/transport/transport.go @@ -0,0 +1,58 @@ +package transport + +import ( + "net/http" + "time" + + "gitlab.com/gitlab-org/labkit/correlation" + "gitlab.com/gitlab-org/labkit/tracing" + + "gitlab.com/gitlab-org/gitlab/workhorse/internal/version" +) + +// Creates a new default transport that has Workhorse's User-Agent header set. +func NewDefaultTransport() http.RoundTripper { + return &DefaultTransport{Next: http.DefaultTransport} +} + +// Defines a http.Transport with values that are more restrictive than for +// http.DefaultTransport, they define shorter TLS Handshake, and more +// aggressive connection closing to prevent the connection hanging and reduce +// FD usage +func NewRestrictedTransport(options ...Option) http.RoundTripper { + return &DefaultTransport{Next: newRestrictedTransport(options...)} +} + +type DefaultTransport struct { + Next http.RoundTripper +} + +func (t DefaultTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req.Header.Set("User-Agent", version.GetUserAgent()) + + return t.Next.RoundTrip(req) +} + +type Option func(*http.Transport) + +func WithDisabledCompression() Option { + return func(t *http.Transport) { + t.DisableCompression = true + } +} + +func newRestrictedTransport(options ...Option) http.RoundTripper { + t := http.DefaultTransport.(*http.Transport).Clone() + + // To avoid keep around TCP connections to http servers we're done with + t.MaxIdleConns = 2 + + // A stricter timeout for fetching from external sources that can be slow + t.ResponseHeaderTimeout = 30 * time.Second + + for _, option := range options { + option(t) + } + + return tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(t)) +} diff --git a/workhorse/internal/upload/destination/objectstore/object.go b/workhorse/internal/upload/destination/objectstore/object.go index 36ffa0eb12e725bf8d18af63effaa9163cece592..1086332312c0f96151d2d464002287446173d988 100644 --- a/workhorse/internal/upload/destination/objectstore/object.go +++ b/workhorse/internal/upload/destination/objectstore/object.go @@ -8,11 +8,11 @@ import ( "gitlab.com/gitlab-org/labkit/mask" - "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport" ) var httpClient = &http.Client{ - Transport: httptransport.New(), + Transport: transport.NewRestrictedTransport(), } // Object represents an object on a S3 compatible Object Store service. diff --git a/workhorse/internal/version/version.go b/workhorse/internal/version/version.go new file mode 100644 index 0000000000000000000000000000000000000000..790edf8ffca9b6b8ed1d638cadfd57db23121795 --- /dev/null +++ b/workhorse/internal/version/version.go @@ -0,0 +1,20 @@ +package version + +import "fmt" + +var version = "unknown" +var build = "unknown" +var schema = "gitlab-workhorse (%s)-(%s)" + +func SetVersion(v, b string) { + version = v + build = b +} + +func GetUserAgent() string { + return GetApplicationVersion() +} + +func GetApplicationVersion() string { + return fmt.Sprintf(schema, version, build) +} diff --git a/workhorse/internal/version/version_test.go b/workhorse/internal/version/version_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9d0581e093b3de507976f760ee1ffc80e9709166 --- /dev/null +++ b/workhorse/internal/version/version_test.go @@ -0,0 +1,19 @@ +package version + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestVersion(t *testing.T) { + require.Equal(t, GetApplicationVersion(), "gitlab-workhorse (unknown)-(unknown)") + + SetVersion("15.3", "123.123") + + require.Equal(t, GetApplicationVersion(), "gitlab-workhorse (15.3)-(123.123)") + + SetVersion("", "123.123") + + require.Equal(t, GetApplicationVersion(), "gitlab-workhorse ()-(123.123)") +} diff --git a/workhorse/internal/zipartifacts/open_archive.go b/workhorse/internal/zipartifacts/open_archive.go index 881ef915d75dad73abecbd2cbd4c96da0d51b5cb..d477725a39f722c661cca6129779865b88d0a1fa 100644 --- a/workhorse/internal/zipartifacts/open_archive.go +++ b/workhorse/internal/zipartifacts/open_archive.go @@ -8,16 +8,16 @@ import ( "os" "strings" - "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport" "gitlab.com/gitlab-org/gitlab/workhorse/internal/httprs" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/transport" zip "gitlab.com/gitlab-org/golang-archive-zip" "gitlab.com/gitlab-org/labkit/mask" ) var httpClient = &http.Client{ - Transport: httptransport.New( - httptransport.WithDisabledCompression(), // To avoid bugs when serving compressed files from object storage + Transport: transport.NewRestrictedTransport( + transport.WithDisabledCompression(), // To avoid bugs when serving compressed files from object storage ), } diff --git a/workhorse/main.go b/workhorse/main.go index b0f9760b0d5dbe2eb07796cfa62d905c4b4d77ab..ca9b86de528a73f78d3c9e0808634d628cb1c04b 100644 --- a/workhorse/main.go +++ b/workhorse/main.go @@ -23,6 +23,7 @@ import ( "gitlab.com/gitlab-org/gitlab/workhorse/internal/redis" "gitlab.com/gitlab-org/gitlab/workhorse/internal/secret" "gitlab.com/gitlab-org/gitlab/workhorse/internal/upstream" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/version" ) // Version is the current version of GitLab Workhorse @@ -55,8 +56,10 @@ func main() { os.Exit(2) } + version.SetVersion(Version, BuildTime) + if boot.printVersion { - fmt.Printf("gitlab-workhorse %s-%s\n", Version, BuildTime) + fmt.Println(version.GetApplicationVersion()) os.Exit(0) }