Skip to content

Commit 90f34d5

Browse files
author
Paulo Gomes
authored
Merge pull request #637 from pjbgf/fix-managed-transport
Various fixes for managed transport
2 parents f6b86cc + 92ad1f8 commit 90f34d5

File tree

11 files changed

+378
-104
lines changed

11 files changed

+378
-104
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ require (
3939
github.com/onsi/gomega v1.18.1
4040
github.com/otiai10/copy v1.7.0
4141
github.com/spf13/pflag v1.0.5
42-
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
42+
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
4343
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
4444
google.golang.org/api v0.73.0
4545
gotest.tools v2.2.0+incompatible

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,8 @@ golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0
11531153
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
11541154
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
11551155
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
1156+
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s=
1157+
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
11561158
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
11571159
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
11581160
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=

internal/helm/repository/chart_repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import (
3939
"github.com/fluxcd/pkg/version"
4040

4141
"github.com/fluxcd/source-controller/internal/helm"
42-
transport "github.com/fluxcd/source-controller/internal/helm/getter"
42+
"github.com/fluxcd/source-controller/internal/transport"
4343
)
4444

4545
var ErrNoChartIndex = errors.New("no chart index")

internal/helm/getter/transport.go renamed to internal/transport/transport.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package getter
17+
package transport
1818

1919
import (
2020
"crypto/tls"

internal/helm/getter/transport_test.go renamed to internal/transport/transport_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package getter
17+
package transport
1818

1919
import (
2020
"crypto/tls"

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func main() {
228228
}()
229229

230230
if managed.Enabled() {
231-
managed.InitManagedTransport()
231+
managed.InitManagedTransport(ctrl.Log.WithName("managed-transport"))
232232
}
233233

234234
setupLog.Info("starting manager")

pkg/git/libgit2/managed/http.go

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,11 @@ import (
5050
"errors"
5151
"fmt"
5252
"io"
53-
"net"
5453
"net/http"
5554
"net/url"
5655
"sync"
57-
"time"
5856

57+
pool "github.com/fluxcd/source-controller/internal/transport"
5958
git2go "github.com/libgit2/git2go/v33"
6059
)
6160

@@ -73,15 +72,18 @@ func registerManagedHTTP() error {
7372
}
7473

7574
func httpSmartSubtransportFactory(remote *git2go.Remote, transport *git2go.Transport) (git2go.SmartSubtransport, error) {
75+
traceLog.Info("[http]: httpSmartSubtransportFactory")
7676
sst := &httpSmartSubtransport{
77-
transport: transport,
77+
transport: transport,
78+
httpTransport: pool.NewOrIdle(nil),
7879
}
7980

8081
return sst, nil
8182
}
8283

8384
type httpSmartSubtransport struct {
84-
transport *git2go.Transport
85+
transport *git2go.Transport
86+
httpTransport *http.Transport
8587
}
8688

8789
func (t *httpSmartSubtransport) Action(targetUrl string, action git2go.SmartServiceAction) (git2go.SmartSubtransportStream, error) {
@@ -104,25 +106,10 @@ func (t *httpSmartSubtransport) Action(targetUrl string, action git2go.SmartServ
104106
proxyFn = http.ProxyURL(parsedUrl)
105107
}
106108

107-
httpTransport := &http.Transport{
108-
// Add the proxy to the http transport.
109-
Proxy: proxyFn,
110-
111-
// Set reasonable timeouts to ensure connections are not
112-
// left open in an idle state, nor they hang indefinitely.
113-
//
114-
// These are based on the official go http.DefaultTransport:
115-
DialContext: (&net.Dialer{
116-
Timeout: 30 * time.Second,
117-
KeepAlive: 30 * time.Second,
118-
}).DialContext,
119-
MaxIdleConns: 100,
120-
IdleConnTimeout: 90 * time.Second,
121-
TLSHandshakeTimeout: 10 * time.Second,
122-
ExpectContinueTimeout: 1 * time.Second,
123-
}
109+
t.httpTransport.Proxy = proxyFn
110+
t.httpTransport.DisableCompression = false
124111

125-
client, req, err := createClientRequest(targetUrl, action, httpTransport)
112+
client, req, err := createClientRequest(targetUrl, action, t.httpTransport)
126113
if err != nil {
127114
return nil, err
128115
}
@@ -223,10 +210,18 @@ func createClientRequest(targetUrl string, action git2go.SmartServiceAction, t *
223210
}
224211

225212
func (t *httpSmartSubtransport) Close() error {
213+
traceLog.Info("[http]: httpSmartSubtransport.Close()")
226214
return nil
227215
}
228216

229217
func (t *httpSmartSubtransport) Free() {
218+
traceLog.Info("[http]: httpSmartSubtransport.Free()")
219+
220+
if t.httpTransport != nil {
221+
traceLog.Info("[http]: release http transport back to pool")
222+
pool.Release(t.httpTransport)
223+
t.httpTransport = nil
224+
}
230225
}
231226

232227
type httpSmartSubtransportStream struct {
@@ -291,7 +286,15 @@ func (self *httpSmartSubtransportStream) Write(buf []byte) (int, error) {
291286

292287
func (self *httpSmartSubtransportStream) Free() {
293288
if self.resp != nil {
294-
self.resp.Body.Close()
289+
traceLog.Info("[http]: httpSmartSubtransportStream.Free()")
290+
291+
if self.resp.Body != nil {
292+
// ensure body is fully processed and closed
293+
// for increased likelihood of transport reuse in HTTP/1.x.
294+
// it should not be a problem to do this more than once.
295+
_, _ = io.Copy(io.Discard, self.resp.Body) // errors can be safely ignored
296+
_ = self.resp.Body.Close() // errors can be safely ignored
297+
}
295298
}
296299
}
297300

@@ -354,6 +357,7 @@ func (self *httpSmartSubtransportStream) sendRequest() error {
354357
}
355358

356359
req.SetBasicAuth(userName, password)
360+
traceLog.Info("[http]: new request", "method", req.Method, "URL", req.URL)
357361
resp, err = self.client.Do(req)
358362
if err != nil {
359363
return err
@@ -362,21 +366,36 @@ func (self *httpSmartSubtransportStream) sendRequest() error {
362366
// GET requests will be automatically redirected.
363367
// POST require the new destination, and also the body content.
364368
if req.Method == "POST" && resp.StatusCode >= 301 && resp.StatusCode <= 308 {
369+
// ensure body is fully processed and closed
370+
// for increased likelihood of transport reuse in HTTP/1.x.
371+
_, _ = io.Copy(io.Discard, resp.Body) // errors can be safely ignored
372+
373+
if err := resp.Body.Close(); err != nil {
374+
return err
375+
}
376+
365377
// The next try will go against the new destination
366378
self.req.URL, err = resp.Location()
367379
if err != nil {
368380
return err
369381
}
370382

383+
traceLog.Info("[http]: POST redirect", "URL", self.req.URL)
371384
continue
372385
}
373386

387+
// for HTTP 200, the response will be cleared up by Free()
374388
if resp.StatusCode == http.StatusOK {
375389
break
376390
}
377391

378-
io.Copy(io.Discard, resp.Body)
379-
defer resp.Body.Close()
392+
// ensure body is fully processed and closed
393+
// for increased likelihood of transport reuse in HTTP/1.x.
394+
_, _ = io.Copy(io.Discard, resp.Body) // errors can be safely ignored
395+
if err := resp.Body.Close(); err != nil {
396+
return err
397+
}
398+
380399
return fmt.Errorf("Unhandled HTTP error %s", resp.Status)
381400
}
382401

pkg/git/libgit2/managed/init.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ package managed
1919
import (
2020
"sync"
2121
"time"
22+
23+
"github.com/fluxcd/pkg/runtime/logger"
24+
"github.com/go-logr/logr"
2225
)
2326

2427
var (
@@ -34,6 +37,9 @@ var (
3437
// regardless of the current operation (i.e. connection,
3538
// handshake, put/get).
3639
fullHttpClientTimeOut time.Duration = 10 * time.Minute
40+
41+
debugLog logr.Logger
42+
traceLog logr.Logger
3743
)
3844

3945
// InitManagedTransport initialises HTTP(S) and SSH managed transport
@@ -47,9 +53,14 @@ var (
4753
//
4854
// This function will only register managed transports once, subsequent calls
4955
// leads to no-op.
50-
func InitManagedTransport() error {
56+
func InitManagedTransport(log logr.Logger) error {
5157
var err error
58+
5259
once.Do(func() {
60+
log.Info("Enabling experimental managed transport")
61+
debugLog = log.V(logger.DebugLevel)
62+
traceLog = log.V(logger.TraceLevel)
63+
5364
if err = registerManagedHTTP(); err != nil {
5465
return
5566
}

0 commit comments

Comments
 (0)