Skip to content

Commit 82cd05e

Browse files
author
Paulo Gomes
authored
Merge pull request #727 from aryan9600/improve-managed
Remove dependency on libgit2 credentials callback
2 parents 5c9a844 + 972d1ca commit 82cd05e

22 files changed

+1409
-1175
lines changed

controllers/gitrepository_controller.go

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -455,33 +455,6 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context,
455455
return sreconcile.ResultEmpty, e
456456
}
457457

458-
repositoryURL := obj.Spec.URL
459-
// managed GIT transport only affects the libgit2 implementation
460-
if managed.Enabled() && obj.Spec.GitImplementation == sourcev1.LibGit2Implementation {
461-
// At present only HTTP connections have the ability to define remote options.
462-
// Although this can be easily extended by ensuring that the fake URL below uses the
463-
// target ssh scheme, and the libgit2/managed/ssh.go pulls that information accordingly.
464-
//
465-
// This is due to the fact the key libgit2 remote callbacks do not take place for HTTP
466-
// whilst most still work for SSH.
467-
if strings.HasPrefix(repositoryURL, "http") {
468-
// Due to the lack of the callback feature, a fake target URL is created to allow
469-
// for the smart sub transport be able to pick the options specific for this
470-
// GitRepository object.
471-
// The URL should use unique information that do not collide in a multi tenant
472-
// deployment.
473-
repositoryURL = fmt.Sprintf("http://%s/%s/%d", obj.Name, obj.UID, obj.Generation)
474-
managed.AddTransportOptions(repositoryURL,
475-
managed.TransportOptions{
476-
TargetURL: obj.Spec.URL,
477-
CABundle: authOpts.CAFile,
478-
})
479-
480-
// We remove the options from memory, to avoid accumulating unused options over time.
481-
defer managed.RemoveTransportOptions(repositoryURL)
482-
}
483-
}
484-
485458
// Fetch the included artifact metadata.
486459
artifacts, err := r.fetchIncludes(ctx, obj)
487460
if err != nil {
@@ -503,7 +476,7 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context,
503476
optimizedClone = true
504477
}
505478

506-
c, err := r.gitCheckout(ctx, obj, repositoryURL, authOpts, dir, optimizedClone)
479+
c, err := r.gitCheckout(ctx, obj, authOpts, dir, optimizedClone)
507480
if err != nil {
508481
return sreconcile.ResultEmpty, err
509482
}
@@ -537,7 +510,7 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context,
537510

538511
// If we can't skip the reconciliation, checkout again without any
539512
// optimization.
540-
c, err := r.gitCheckout(ctx, obj, repositoryURL, authOpts, dir, false)
513+
c, err := r.gitCheckout(ctx, obj, authOpts, dir, false)
541514
if err != nil {
542515
return sreconcile.ResultEmpty, err
543516
}
@@ -729,7 +702,7 @@ func (r *GitRepositoryReconciler) reconcileInclude(ctx context.Context,
729702
// gitCheckout builds checkout options with the given configurations and
730703
// performs a git checkout.
731704
func (r *GitRepositoryReconciler) gitCheckout(ctx context.Context,
732-
obj *sourcev1.GitRepository, repoURL string, authOpts *git.AuthOptions, dir string, optimized bool) (*git.Commit, error) {
705+
obj *sourcev1.GitRepository, authOpts *git.AuthOptions, dir string, optimized bool) (*git.Commit, error) {
733706
// Configure checkout strategy.
734707
checkoutOpts := git.CheckoutOptions{RecurseSubmodules: obj.Spec.RecurseSubmodules}
735708
if ref := obj.Spec.Reference; ref != nil {
@@ -755,15 +728,34 @@ func (r *GitRepositoryReconciler) gitCheckout(ctx context.Context,
755728
Err: fmt.Errorf("failed to configure checkout strategy for Git implementation '%s': %w", obj.Spec.GitImplementation, err),
756729
Reason: sourcev1.GitOperationFailedReason,
757730
}
758-
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Err.Error())
759731
// Do not return err as recovery without changes is impossible.
760732
return nil, e
761733
}
762734

735+
// managed GIT transport only affects the libgit2 implementation
736+
if managed.Enabled() && obj.Spec.GitImplementation == sourcev1.LibGit2Implementation {
737+
// We set the TransportOptionsURL of this set of authentication options here by constructing
738+
// a unique URL that won't clash in a multi tenant environment. This unique URL is used by
739+
// libgit2 managed transports. This enables us to bypass the inbuilt credentials callback in
740+
// libgit2, which is inflexible and unstable.
741+
if strings.HasPrefix(obj.Spec.URL, "http") {
742+
authOpts.TransportOptionsURL = fmt.Sprintf("http://%s/%s/%d", obj.Name, obj.UID, obj.Generation)
743+
} else if strings.HasPrefix(obj.Spec.URL, "ssh") {
744+
authOpts.TransportOptionsURL = fmt.Sprintf("ssh://%s/%s/%d", obj.Name, obj.UID, obj.Generation)
745+
} else {
746+
e := &serror.Stalling{
747+
Err: fmt.Errorf("git repository URL has invalid transport type: '%s'", obj.Spec.URL),
748+
Reason: sourcev1.URLInvalidReason,
749+
}
750+
return nil, e
751+
}
752+
}
753+
763754
// Checkout HEAD of reference in object
764755
gitCtx, cancel := context.WithTimeout(ctx, obj.Spec.Timeout.Duration)
765756
defer cancel()
766-
commit, err := checkoutStrategy.Checkout(gitCtx, dir, repoURL, authOpts)
757+
758+
commit, err := checkoutStrategy.Checkout(gitCtx, dir, obj.Spec.URL, authOpts)
767759
if err != nil {
768760
e := serror.NewGeneric(
769761
fmt.Errorf("failed to checkout and determine revision: %w", err),

controllers/suite_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/fluxcd/pkg/runtime/controller"
4040
"github.com/fluxcd/pkg/runtime/testenv"
4141
"github.com/fluxcd/pkg/testserver"
42+
"github.com/go-logr/logr"
4243
"github.com/phayes/freeport"
4344

4445
"github.com/distribution/distribution/v3/configuration"
@@ -50,6 +51,7 @@ import (
5051
"github.com/fluxcd/source-controller/internal/cache"
5152
"github.com/fluxcd/source-controller/internal/features"
5253
"github.com/fluxcd/source-controller/internal/helm/registry"
54+
"github.com/fluxcd/source-controller/pkg/git/libgit2/managed"
5355
// +kubebuilder:scaffold:imports
5456
)
5557

@@ -207,6 +209,8 @@ func TestMain(m *testing.M) {
207209
panic(fmt.Sprintf("Failed to create OCI registry client"))
208210
}
209211

212+
managed.InitManagedTransport(logr.Discard())
213+
210214
if err := (&GitRepositoryReconciler{
211215
Client: testEnv,
212216
EventRecorder: record.NewFakeRecorder(32),

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/fluxcd/pkg/helmtestserver v0.7.2
2929
github.com/fluxcd/pkg/lockedfile v0.1.0
3030
github.com/fluxcd/pkg/runtime v0.16.1
31-
github.com/fluxcd/pkg/ssh v0.3.4
31+
github.com/fluxcd/pkg/ssh v0.4.0
3232
github.com/fluxcd/pkg/testserver v0.2.0
3333
github.com/fluxcd/pkg/untar v0.1.0
3434
github.com/fluxcd/pkg/version v0.1.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,8 @@ github.com/fluxcd/pkg/lockedfile v0.1.0 h1:YsYFAkd6wawMCcD74ikadAKXA4s2sukdxrn7w
282282
github.com/fluxcd/pkg/lockedfile v0.1.0/go.mod h1:EJLan8t9MiOcgTs8+puDjbE6I/KAfHbdvIy9VUgIjm8=
283283
github.com/fluxcd/pkg/runtime v0.16.1 h1:WU1vNZz4TAzmATQ/tl2zB/FX6GIUTgYeBn/G5RuTA2c=
284284
github.com/fluxcd/pkg/runtime v0.16.1/go.mod h1:cgVJkOXCg9OmrIUGklf/0UtV28MNzkuoBJhaEQICT6E=
285-
github.com/fluxcd/pkg/ssh v0.3.4 h1:Ko+MUNiiQG3evyoMO19iRk7d4X0VJ6w6+GEeVQ1jLC0=
286-
github.com/fluxcd/pkg/ssh v0.3.4/go.mod h1:KGgOUOy1uI6RC6+qxIBLvP1AeOOs/nLB25Ca6TZMIXE=
285+
github.com/fluxcd/pkg/ssh v0.4.0 h1:2HY88irZ5BCSMlzZExR6cnhRkjxCDsK/lTHHQqCJDJQ=
286+
github.com/fluxcd/pkg/ssh v0.4.0/go.mod h1:KGgOUOy1uI6RC6+qxIBLvP1AeOOs/nLB25Ca6TZMIXE=
287287
github.com/fluxcd/pkg/testserver v0.2.0 h1:Mj0TapmKaywI6Fi5wvt1LAZpakUHmtzWQpJNKQ0Krt4=
288288
github.com/fluxcd/pkg/testserver v0.2.0/go.mod h1:bgjjydkXsZTeFzjz9Cr4heGANr41uTB1Aj1Q5qzuYVk=
289289
github.com/fluxcd/pkg/untar v0.1.0 h1:k97V/xV5hFrAkIkVPuv5AVhyxh1ZzzAKba/lbDfGo6o=

internal/features/features.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,11 @@ func FeatureGates() map[string]bool {
6565
func Enabled(feature string) (bool, error) {
6666
return feathelper.Enabled(feature)
6767
}
68+
69+
// Disable disables the specified feature. If the feature is not
70+
// present, it's a no-op.
71+
func Disable(feature string) {
72+
if _, ok := features[feature]; ok {
73+
features[feature] = false
74+
}
75+
}

main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,13 @@ func main() {
312312

313313
if enabled, _ := features.Enabled(features.GitManagedTransport); enabled {
314314
managed.InitManagedTransport(ctrl.Log.WithName("managed-transport"))
315+
} else {
316+
if optimize, _ := feathelper.Enabled(features.OptimizedGitClones); optimize {
317+
features.Disable(features.OptimizedGitClones)
318+
setupLog.Info(
319+
"disabling optimized git clones; git clones can only be optimized when using managed transport",
320+
)
321+
}
315322
}
316323

317324
setupLog.Info("starting manager")

0 commit comments

Comments
 (0)