Implement Managed Transport for libgit2

libgit2 network operations are blocking and do not provide timeout nor context capabilities,
leading to several reports of the controllers hanging indefinitely.

By using managed transport, golang primitives such as http.Transport and net.Dial can be used
to ensure timeouts are enforced.

Signed-off-by: Paulo Gomes <paulo.gomes@weave.works>
This commit is contained in:
Paulo Gomes 2022-03-21 15:19:00 +00:00
parent 4d8ebe69a0
commit 5b15bb7f94
No known key found for this signature in database
GPG Key ID: 9995233870E99BEE
2 changed files with 35 additions and 6 deletions

View File

@ -62,6 +62,7 @@ import (
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/fluxcd/source-controller/pkg/git"
gitlibgit2 "github.com/fluxcd/source-controller/pkg/git/libgit2"
"github.com/fluxcd/source-controller/pkg/git/libgit2/managed"
gitstrat "github.com/fluxcd/source-controller/pkg/git/strategy"
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
@ -247,6 +248,34 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(ctx context.Context, req ctr
return failWithError(err)
}
repositoryURL := origin.Spec.URL
if managed.Enabled() {
// At present only HTTP connections have the ability to define remote options.
// Although this can be easily extended by ensuring that the fake URL below uses the
// target ssh scheme, and the libgit2/managed/ssh.go pulls that information accordingly.
//
// This is due to the fact the key libgit2 remote callbacks do not take place for HTTP
// whilst most still work for SSH.
if strings.HasPrefix(repositoryURL, "http") {
if access.auth != nil && len(access.auth.CAFile) > 0 {
// Due to the lack of the callback feature, a fake target URL is created to allow
// for the smart sub transport be able to pick the options specific for this
// GitRepository object.
// The URL should use unique information that do not collide in a multi tenant
// deployment.
repositoryURL = fmt.Sprintf("http://%s/%s/%d", auto.Name, auto.UID, auto.Generation)
managed.AddTransportOptions(repositoryURL,
managed.TransportOptions{
TargetURL: repositoryURL,
CABundle: access.auth.CAFile,
})
// We remove the options from memory, to avoid accumulating unused options over time.
defer managed.RemoveTransportOptions(repositoryURL)
}
}
}
// Use the git operations timeout for the repo.
cloneCtx, cancel := context.WithTimeout(ctx, origin.Spec.Timeout.Duration)
defer cancel()
@ -470,12 +499,6 @@ func (r *ImageUpdateAutomationReconciler) automationsForImagePolicy(obj client.O
return reqs
}
// --- git ops
// Note: libgit2 is always used for network operations; for cloning,
// it will do a non-shallow clone, and for anything else, it doesn't
// matter what is used.
type repoAccess struct {
auth *git.AuthOptions
url string

View File

@ -40,6 +40,8 @@ import (
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
"github.com/fluxcd/source-controller/pkg/git/libgit2/managed"
// +kubebuilder:scaffold:imports
"github.com/fluxcd/image-automation-controller/controllers"
)
@ -137,6 +139,10 @@ func main() {
}
// +kubebuilder:scaffold:builder
if managed.Enabled() {
managed.InitManagedTransport()
}
setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")