Skip to content

Commit

Permalink
gogit: Add new ForceGoGitImplementation FeatureGate
Browse files Browse the repository at this point in the history
ForceGoGitImplementation ignores the value set for gitImplementation
and ensures that go-git is used for all GitRepository objects.
This can be used to confirm that Flux instances won't break if/when
the libgit2 implementation was to be deprecated.

When enabled, libgit2 won't be initialized, nor will any git2go cgo
code be called.

Signed-off-by: Paulo Gomes <paulo.gomes@weave.works>
  • Loading branch information
Paulo Gomes committed Nov 4, 2022
1 parent d293039 commit 823147a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 17 deletions.
16 changes: 14 additions & 2 deletions controllers/imageupdateautomation_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import (
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"

imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
"github.com/fluxcd/image-automation-controller/internal/features"
"github.com/fluxcd/image-automation-controller/pkg/update"
)

Expand All @@ -85,6 +86,8 @@ type ImageUpdateAutomationReconciler struct {
helper.Metrics

NoCrossNamespaceRef bool

features map[string]bool
}

type ImageUpdateAutomationReconcilerOptions struct {
Expand Down Expand Up @@ -254,14 +257,19 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(ctx context.Context, req ctr
return failWithError(err)
}

gitImplementation := origin.Spec.GitImplementation
if goGitOnly, _ := r.features[features.ForceGoGitImplementation]; goGitOnly {
gitImplementation = sourcev1.GoGitImplementation
}

var gitClient git.RepositoryClient
switch origin.Spec.GitImplementation {
switch gitImplementation {
case sourcev1.LibGit2Implementation:
gitClient, err = libgit2.NewClient(tmp, authOpts)
case sourcev1.GoGitImplementation, "":
gitClient, err = gogit.NewClient(tmp, authOpts)
default:
err = fmt.Errorf("failed to create git client; referred GitRepository has invalid implementation: %s", origin.Spec.GitImplementation)
err = fmt.Errorf("failed to create git client; referred GitRepository has invalid implementation: %s", gitImplementation)
}
if err != nil {
return failWithError(err)
Expand Down Expand Up @@ -416,6 +424,10 @@ func (r *ImageUpdateAutomationReconciler) SetupWithManager(mgr ctrl.Manager, opt
return err
}

if r.features == nil {
r.features = features.FeatureGates()
}

return ctrl.NewControllerManagedBy(mgr).
For(&imagev1.ImageUpdateAutomation{}, builder.WithPredicates(
predicate.Or(predicate.GenerationChangedPredicate{}, predicates.ReconcileRequestedPredicate{}))).
Expand Down
26 changes: 21 additions & 5 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"

imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
"github.com/fluxcd/image-automation-controller/internal/features"
// +kubebuilder:scaffold:imports
)

Expand All @@ -60,19 +61,34 @@ func TestMain(m *testing.M) {
utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme))
utilruntime.Must(imagev1.AddToScheme(scheme.Scheme))

if err := transport.InitManagedTransport(); err != nil {
panic(fmt.Sprintf("failed to initialize libgit2 managed transport: %v", err))
}

code := runTestsWithFeatures(m, nil)
if code != 0 {
fmt.Println("failed with default feature values")
os.Exit(code)
}

code = runTestsWithFeatures(m, map[string]bool{
features.ForceGoGitImplementation: false,
})

os.Exit(code)
}

func runTestsWithFeatures(m *testing.M, feats map[string]bool) int {
testEnv = testenv.New(testenv.WithCRDPath(
filepath.Join("..", "config", "crd", "bases"),
filepath.Join("testdata", "crds"),
))

if err := transport.InitManagedTransport(); err != nil {
panic(fmt.Sprintf("failed to initialize libgit2 managed transport: %v", err))
}

controllerName := "image-automation-controller"
if err := (&ImageUpdateAutomationReconciler{
Client: testEnv,
EventRecorder: testEnv.GetEventRecorderFor(controllerName),
features: feats,
}).SetupWithManager(testEnv, ImageUpdateAutomationReconcilerOptions{}); err != nil {
panic(fmt.Sprintf("failed to start ImageUpdateAutomationReconciler: %v", err))
}
Expand All @@ -92,7 +108,7 @@ func TestMain(m *testing.M) {
panic(fmt.Sprintf("failed to stop the test environment: %v", err))
}

os.Exit(code)
return code
}

// This provides a regression assurance for image-automation-controller/#339.
Expand Down
17 changes: 10 additions & 7 deletions internal/features/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ package features
import feathelper "github.com/fluxcd/pkg/runtime/features"

const (
// GitManagedTransport implements a managed transport for GitRepository
// objects that use the libgit2 implementation.
// ForceGoGitImplementation ignores the value set for gitImplementation
// of a GitRepository object and ensures that go-git is used for all git operations.
//
// When enabled, improves the reliability of libgit2 reconciliations,
// by enforcing timeouts and ensuring libgit2 cannot hijack the process
// and hang it indefinitely.
GitManagedTransport = "GitManagedTransport"
// When enabled, libgit2 won't be initialized, nor will any git2go cgo
// code be called.
ForceGoGitImplementation = "ForceGoGitImplementation"
)

var features = map[string]bool{}
var features = map[string]bool{
// ForceGoGitImplementation
// opt-out from v0.32
ForceGoGitImplementation: true,
}

// DefaultFeatureGates contains a list of all supported feature gates and
// their default values.
Expand Down
8 changes: 5 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,11 @@ func main() {
}
// +kubebuilder:scaffold:builder

if err = transport.InitManagedTransport(); err != nil {
setupLog.Error(err, "unable to initialize libgit2 managed transport")
os.Exit(1)
if gogitOnly, _ := features.Enabled(features.ForceGoGitImplementation); !gogitOnly {
if err = transport.InitManagedTransport(); err != nil {
setupLog.Error(err, "unable to initialize libgit2 managed transport")
os.Exit(1)
}
}

setupLog.Info("starting manager")
Expand Down

0 comments on commit 823147a

Please sign in to comment.