Merge pull request #1802 from fluxcd/rfc-0010-feature-gate

[RFC-0010] Introduce feature gate
This commit is contained in:
Matheus Pimenta 2025-05-23 07:59:19 +01:00 committed by GitHub
commit 0d9ed5936f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 195 additions and 69 deletions

View File

@ -4,7 +4,7 @@ go 1.24.0
require (
github.com/fluxcd/pkg/apis/acl v0.7.0
github.com/fluxcd/pkg/apis/meta v1.11.0
github.com/fluxcd/pkg/apis/meta v1.12.0
k8s.io/apimachinery v0.33.0
sigs.k8s.io/controller-runtime v0.20.4
)

View File

@ -5,8 +5,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0=
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
github.com/fluxcd/pkg/apis/meta v1.11.0 h1:h8q95k6ZEK1HCfsLkt8Np3i6ktb6ZzcWJ6hg++oc9w0=
github.com/fluxcd/pkg/apis/meta v1.11.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=

10
go.mod
View File

@ -23,16 +23,16 @@ require (
github.com/elazarl/goproxy v1.7.2
github.com/fluxcd/cli-utils v0.36.0-flux.13
github.com/fluxcd/pkg/apis/event v0.17.0
github.com/fluxcd/pkg/apis/meta v1.11.0
github.com/fluxcd/pkg/auth v0.12.0
github.com/fluxcd/pkg/apis/meta v1.12.0
github.com/fluxcd/pkg/auth v0.14.0
github.com/fluxcd/pkg/cache v0.9.0
github.com/fluxcd/pkg/git v0.29.0
github.com/fluxcd/pkg/git/gogit v0.31.0
github.com/fluxcd/pkg/git v0.31.0
github.com/fluxcd/pkg/git/gogit v0.33.0
github.com/fluxcd/pkg/gittestserver v0.17.0
github.com/fluxcd/pkg/helmtestserver v0.24.0
github.com/fluxcd/pkg/lockedfile v0.6.0
github.com/fluxcd/pkg/masktoken v0.7.0
github.com/fluxcd/pkg/oci v0.48.0
github.com/fluxcd/pkg/oci v0.49.0
github.com/fluxcd/pkg/runtime v0.59.0
github.com/fluxcd/pkg/sourceignore v0.12.0
github.com/fluxcd/pkg/ssh v0.18.0

20
go.sum
View File

@ -372,16 +372,16 @@ github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5o
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
github.com/fluxcd/pkg/apis/event v0.17.0 h1:foEINE++pCJlWVhWjYDXfkVmGKu8mQ4BDBlbYi5NU7M=
github.com/fluxcd/pkg/apis/event v0.17.0/go.mod h1:0fLhLFiHlRTDKPDXdRnv+tS7mCMIQ0fJxnEfmvGM/5A=
github.com/fluxcd/pkg/apis/meta v1.11.0 h1:h8q95k6ZEK1HCfsLkt8Np3i6ktb6ZzcWJ6hg++oc9w0=
github.com/fluxcd/pkg/apis/meta v1.11.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
github.com/fluxcd/pkg/auth v0.12.0 h1:35o0ziYMLZVgJwNvJBGsv/wd903B2fMagcrnm1ptUjc=
github.com/fluxcd/pkg/auth v0.12.0/go.mod h1:gQD2VT5OhIR1E8ZTEsTaho3bDQZidr9P10smH/awcew=
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
github.com/fluxcd/pkg/auth v0.14.0 h1:AA9nmbFzTN5jcGROJK51LvQoDetMrXJLAo4Sd6WHpFI=
github.com/fluxcd/pkg/auth v0.14.0/go.mod h1:o91WIZZshLooBALXY/MVn0mmdUw3eATrqGXrG1M7nTE=
github.com/fluxcd/pkg/cache v0.9.0 h1:EGKfOLMG3fOwWnH/4Axl5xd425mxoQbZzlZoLfd8PDk=
github.com/fluxcd/pkg/cache v0.9.0/go.mod h1:jMwabjWfsC5lW8hE7NM3wtGNwSJ38Javx6EKbEi7INU=
github.com/fluxcd/pkg/git v0.29.0 h1:MHQ4F53e6Xt8a/POkd/fiChgysnd/XqiuK7vOWXAXLk=
github.com/fluxcd/pkg/git v0.29.0/go.mod h1:Ygn+LfrK6Ok+85uiq6s3NWG5LcHS4KY7mzES2JDJsGY=
github.com/fluxcd/pkg/git/gogit v0.31.0 h1:A56cmtgJBkWAj+gXSOdhPMQVTx0VF91S0PUaqpMXN4g=
github.com/fluxcd/pkg/git/gogit v0.31.0/go.mod h1:ya8z22xTvAAdW12HycxKYv4S+G+lqu5Kx/LyO/jWz8Y=
github.com/fluxcd/pkg/git v0.31.0 h1:hVUJcRujNa+GA5zrjrMpuVcgHbCBjfq0CZIZJqJl22I=
github.com/fluxcd/pkg/git v0.31.0/go.mod h1:rUgLXVQGBkBggHOLVMhHMHaweQ8Oc6HwZiN2Zm08Zxs=
github.com/fluxcd/pkg/git/gogit v0.33.0 h1:JYKa3XqA91AX7/sKEgARO9VzkwouXWjUgpwudEZEWq0=
github.com/fluxcd/pkg/git/gogit v0.33.0/go.mod h1:EvsVYcB3KjfhpdoyU1sO9HuMH5Xt0cVhW49kFlZcFLY=
github.com/fluxcd/pkg/gittestserver v0.17.0 h1:JlBvWZQTDOI+np5Z+084m3DkeAH1hMusEybyRUDF63k=
github.com/fluxcd/pkg/gittestserver v0.17.0/go.mod h1:E/40EmLoXcMqd6gLuLDC9F6KJxqHVGbBBeMNKk5XdxU=
github.com/fluxcd/pkg/helmtestserver v0.24.0 h1:9sSfRG17GnDIup4sI8V+fdvKROtunU4JyIo34uvXq3Q=
@ -390,8 +390,8 @@ github.com/fluxcd/pkg/lockedfile v0.6.0 h1:64RRMiPv3ZK9Y4sjI8c78kZAdfEo+Sjr2iP8a
github.com/fluxcd/pkg/lockedfile v0.6.0/go.mod h1:gpdUVm7+05NIT1ZvzuNnHfnT81OhZtIySlxxkZ68pXk=
github.com/fluxcd/pkg/masktoken v0.7.0 h1:pitmyOg2pUVdW+nn2Lk/xqm2TaA08uxvOC0ns3sz6bM=
github.com/fluxcd/pkg/masktoken v0.7.0/go.mod h1:Lc1uoDjO1GY6+YdkK+ZqqBIBWquyV58nlSJ5S1N1IYU=
github.com/fluxcd/pkg/oci v0.48.0 h1:iSK4JDM0nx9plSlOGx2aI4td6aQdV/awrfXK/bzI35I=
github.com/fluxcd/pkg/oci v0.48.0/go.mod h1:rnUC8EOpzQp4rugpmopYFMnG3+CR1wqEV3356gHUtSY=
github.com/fluxcd/pkg/oci v0.49.0 h1:L8/dmNSIzqu6X8vzIkPLrW8NAF7Et/SnOuI8WJkXeq8=
github.com/fluxcd/pkg/oci v0.49.0/go.mod h1:iZkF4bQTpc6YOU5IJWMBp0Q8voGm7bkMYiAarJ9407U=
github.com/fluxcd/pkg/runtime v0.59.0 h1:3OrFkMJB39NcQ2vhhoxqls59sQVSn8U+thhyLbsQoA4=
github.com/fluxcd/pkg/runtime v0.59.0/go.mod h1:MFbfyNyyoYRgPxpdwC9/dCOkzo7Yxhu/cQ9NKyhvqc0=
github.com/fluxcd/pkg/sourceignore v0.12.0 h1:jCIe6d50rQ3wdXPF0+PhhqN0XrTRIq3upMomPelI8Mw=

View File

@ -28,6 +28,7 @@ import (
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/fluxcd/pkg/auth"
authutils "github.com/fluxcd/pkg/auth/utils"
"github.com/fluxcd/pkg/git/github"
"github.com/fluxcd/pkg/runtime/logger"
"github.com/go-git/go-git/v5/plumbing/transport"
@ -683,28 +684,28 @@ func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1
return nil, e
}
var authOpts []auth.Option
// Configure provider authentication if specified.
var getCreds func() (*authutils.GitCredentials, error)
switch provider := obj.GetProvider(); provider {
case sourcev1.GitProviderAzure: // If AWS or GCP are added in the future they can be added here separated by a comma.
getCreds = func() (*authutils.GitCredentials, error) {
var opts []auth.Option
if r.TokenCache != nil {
involvedObject := cache.InvolvedObject{
Kind: sourcev1.GitRepositoryKind,
Name: obj.GetName(),
Namespace: obj.GetNamespace(),
Operation: cache.OperationReconcile,
}
authOpts = append(authOpts, auth.WithCache(*r.TokenCache, involvedObject))
}
if r.TokenCache != nil {
involvedObject := cache.InvolvedObject{
Kind: sourcev1.GitRepositoryKind,
Name: obj.GetName(),
Namespace: obj.GetNamespace(),
Operation: cache.OperationReconcile,
}
opts = append(opts, auth.WithCache(*r.TokenCache, involvedObject))
}
if proxyURL != nil {
authOpts = append(authOpts, auth.WithProxyURL(*proxyURL))
}
if proxyURL != nil {
opts = append(opts, auth.WithProxyURL(*proxyURL))
}
// Configure provider authentication if specified in spec
switch obj.GetProvider() {
case sourcev1.GitProviderAzure:
opts.ProviderOpts = &git.ProviderOptions{
Name: sourcev1.GitProviderAzure,
AuthOpts: authOpts,
return authutils.GetGitCredentials(ctx, provider, opts...)
}
case sourcev1.GitProviderGitHub:
// if provider is github, but secret ref is not specified
@ -717,14 +718,30 @@ func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1
return nil, e
}
opts.ProviderOpts = &git.ProviderOptions{
Name: sourcev1.GitProviderGitHub,
GitHubOpts: []github.OptFunc{
github.WithAppData(authData),
github.WithProxyURL(proxyURL),
github.WithCache(r.TokenCache, sourcev1.GitRepositoryKind,
obj.GetName(), obj.GetNamespace(), cache.OperationReconcile),
},
getCreds = func() (*authutils.GitCredentials, error) {
var opts []github.OptFunc
if len(authData) > 0 {
opts = append(opts, github.WithAppData(authData))
}
if proxyURL != nil {
opts = append(opts, github.WithProxyURL(proxyURL))
}
if r.TokenCache != nil {
opts = append(opts, github.WithCache(r.TokenCache, sourcev1.GitRepositoryKind,
obj.GetName(), obj.GetNamespace(), cache.OperationReconcile))
}
username, password, err := github.GetCredentials(ctx, opts...)
if err != nil {
return nil, err
}
return &authutils.GitCredentials{
Username: username,
Password: password,
}, nil
}
default:
// analyze secret, if it has github app data, perhaps provider should have been github.
@ -737,6 +754,20 @@ func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1
return nil, e
}
}
if getCreds != nil {
creds, err := getCreds()
if err != nil {
e := serror.NewGeneric(
fmt.Errorf("failed to configure authentication options: %w", err),
sourcev1.AuthenticationFailedReason,
)
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, "%s", e)
return nil, e
}
opts.BearerToken = creds.BearerToken
opts.Username = creds.Username
opts.Password = creds.Password
}
return opts, nil
}

View File

@ -787,12 +787,11 @@ func TestGitRepositoryReconciler_reconcileSource_authStrategy(t *testing.T) {
func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) {
tests := []struct {
name string
url string
secret *corev1.Secret
beforeFunc func(obj *sourcev1.GitRepository)
wantProviderOptsName string
wantErr error
name string
url string
secret *corev1.Secret
beforeFunc func(obj *sourcev1.GitRepository)
wantErr string
}{
{
name: "azure provider",
@ -800,7 +799,7 @@ func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) {
beforeFunc: func(obj *sourcev1.GitRepository) {
obj.Spec.Provider = sourcev1.GitProviderAzure
},
wantProviderOptsName: sourcev1.GitProviderAzure,
wantErr: "ManagedIdentityCredential",
},
{
name: "github provider with no secret ref",
@ -808,8 +807,7 @@ func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) {
beforeFunc: func(obj *sourcev1.GitRepository) {
obj.Spec.Provider = sourcev1.GitProviderGitHub
},
wantProviderOptsName: sourcev1.GitProviderGitHub,
wantErr: errors.New("secretRef with github app data must be specified when provider is set to github"),
wantErr: "secretRef with github app data must be specified when provider is set to github",
},
{
name: "github provider with github app data in secret",
@ -830,7 +828,7 @@ func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) {
Name: "githubAppSecret",
}
},
wantProviderOptsName: sourcev1.GitProviderGitHub,
wantErr: "Key must be a PEM encoded PKCS1 or PKCS8 key",
},
{
name: "generic provider with github app data in secret",
@ -849,7 +847,7 @@ func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) {
Name: "githubAppSecret",
}
},
wantErr: errors.New("secretRef '/githubAppSecret' has github app data but provider is not set to github"),
wantErr: "secretRef '/githubAppSecret' has github app data but provider is not set to github",
},
{
name: "generic provider",
@ -866,7 +864,7 @@ func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) {
Name: "authSecret",
}
},
wantErr: errors.New("failed to get secret '/authSecret': secrets \"authSecret\" not found"),
wantErr: "failed to get secret '/authSecret': secrets \"authSecret\" not found",
},
{
url: "https://example.com/org/repo",
@ -899,20 +897,19 @@ func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) {
if tt.beforeFunc != nil {
tt.beforeFunc(obj)
}
opts, err := r.getAuthOpts(context.TODO(), obj, *url, nil)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
opts, err := r.getAuthOpts(ctx, obj, *url, nil)
if tt.wantErr != nil {
if tt.wantErr != "" {
g.Expect(err).To(HaveOccurred())
g.Expect(err.Error()).To(ContainSubstring(tt.wantErr.Error()))
g.Expect(err.Error()).To(ContainSubstring(tt.wantErr))
} else {
g.Expect(err).ToNot(HaveOccurred())
g.Expect(opts).ToNot(BeNil())
if tt.wantProviderOptsName != "" {
g.Expect(opts.ProviderOpts).ToNot(BeNil())
g.Expect(opts.ProviderOpts.Name).To(Equal(tt.wantProviderOptsName))
} else {
g.Expect(opts.ProviderOpts).To(BeNil())
}
g.Expect(opts.BearerToken).To(BeEmpty())
g.Expect(opts.Username).To(BeEmpty())
g.Expect(opts.Password).To(BeEmpty())
}
})
}

View File

@ -369,6 +369,13 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
if _, ok := keychain.(soci.Anonymous); obj.Spec.Provider != ociv1.GenericOCIProvider && ok {
var opts []auth.Option
if obj.Spec.ServiceAccountName != "" {
// Check object-level workload identity feature gate.
if !auth.IsObjectLevelWorkloadIdentityEnabled() {
const gate = auth.FeatureGateObjectLevelWorkloadIdentity
const msgFmt = "to use spec.serviceAccountName for provider authentication please enable the %s feature gate in the controller"
err := fmt.Errorf(msgFmt, gate)
return sreconcile.ResultEmpty, serror.NewStalling(err, meta.FeatureGateDisabledReason)
}
serviceAccount := client.ObjectKey{
Name: obj.Spec.ServiceAccountName,
Namespace: obj.GetNamespace(),

View File

@ -60,6 +60,7 @@ import (
kstatus "github.com/fluxcd/cli-utils/pkg/kstatus/status"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/auth"
"github.com/fluxcd/pkg/git"
"github.com/fluxcd/pkg/oci"
"github.com/fluxcd/pkg/runtime/conditions"
@ -2971,10 +2972,10 @@ func TestOCIRepository_getArtifactRef(t *testing.T) {
}
}
func TestOCIRepository_stalled(t *testing.T) {
func TestOCIRepository_invalidURL(t *testing.T) {
g := NewWithT(t)
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-stalled-test")
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-invalid-url-test")
g.Expect(err).ToNot(HaveOccurred())
defer func() { g.Expect(testEnv.Delete(ctx, ns)).To(Succeed()) }()
@ -3013,6 +3014,74 @@ func TestOCIRepository_stalled(t *testing.T) {
g.Expect(stalledCondition.Reason).Should(Equal(sourcev1.URLInvalidReason))
}
func TestOCIRepository_objectLevelWorkloadIdentityFeatureGate(t *testing.T) {
g := NewWithT(t)
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-olwifg-test")
g.Expect(err).ToNot(HaveOccurred())
defer func() { g.Expect(testEnv.Delete(ctx, ns)).To(Succeed()) }()
err = testEnv.Create(ctx, &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns.Name,
Name: "test",
},
})
g.Expect(err).NotTo(HaveOccurred())
obj := &ociv1.OCIRepository{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "ocirepository-reconcile",
Namespace: ns.Name,
},
Spec: ociv1.OCIRepositorySpec{
URL: "oci://ghcr.io/stefanprodan/manifests/podinfo",
Interval: metav1.Duration{Duration: 60 * time.Minute},
Provider: "aws",
ServiceAccountName: "test",
},
}
g.Expect(testEnv.Create(ctx, obj)).To(Succeed())
key := client.ObjectKey{Name: obj.Name, Namespace: obj.Namespace}
resultobj := &ociv1.OCIRepository{}
g.Eventually(func() bool {
if err := testEnv.Get(ctx, key, resultobj); err != nil {
return false
}
return conditions.IsStalled(resultobj)
}).Should(BeTrue())
stalledCondition := conditions.Get(resultobj, meta.StalledCondition)
g.Expect(stalledCondition).ToNot(BeNil())
g.Expect(stalledCondition.Reason).Should(Equal(meta.FeatureGateDisabledReason))
g.Expect(stalledCondition.Message).Should(Equal("to use spec.serviceAccountName for provider authentication please enable the ObjectLevelWorkloadIdentity feature gate in the controller"))
t.Setenv(auth.EnvVarEnableObjectLevelWorkloadIdentity, "true")
g.Eventually(func() bool {
if err := testEnv.Get(ctx, key, resultobj); err != nil {
return false
}
resultobj.Annotations = map[string]string{
meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339),
}
return testEnv.Update(ctx, resultobj) == nil
}).Should(BeTrue())
g.Expect(testEnv.Update(ctx, resultobj)).To(Succeed())
g.Eventually(func() bool {
if err := testEnv.Get(ctx, key, resultobj); err != nil {
return false
}
logOCIRepoStatus(t, resultobj)
return !conditions.IsReady(resultobj) &&
conditions.GetReason(resultobj, meta.ReadyCondition) == sourcev1.AuthenticationFailedReason
}).Should(BeTrue())
}
func TestOCIRepository_reconcileStorage(t *testing.T) {
tests := []struct {
name string

View File

@ -43,6 +43,7 @@ import (
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/distribution/distribution/v3/configuration"
dockerRegistry "github.com/distribution/distribution/v3/registry"
@ -452,3 +453,8 @@ func randStringRunes(n int) string {
func int64p(i int64) *int64 {
return &i
}
func logOCIRepoStatus(t *testing.T, obj *sourcev1beta2.OCIRepository) {
sts, _ := yaml.Marshal(obj.Status)
t.Log(string(sts))
}

View File

@ -19,7 +19,10 @@ limitations under the License.
// states.
package features
import feathelper "github.com/fluxcd/pkg/runtime/features"
import (
"github.com/fluxcd/pkg/auth"
feathelper "github.com/fluxcd/pkg/runtime/features"
)
const (
// CacheSecretsAndConfigMaps controls whether secrets and configmaps should be cached.
@ -35,6 +38,10 @@ var features = map[string]bool{
CacheSecretsAndConfigMaps: false,
}
func init() {
auth.SetFeatureGates(features)
}
// FeatureGates contains a list of all supported feature gates and
// their default values.
func FeatureGates() map[string]bool {

View File

@ -39,6 +39,7 @@ import (
ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"github.com/fluxcd/pkg/auth"
pkgcache "github.com/fluxcd/pkg/cache"
"github.com/fluxcd/pkg/git"
"github.com/fluxcd/pkg/runtime/client"
@ -178,6 +179,14 @@ func main() {
os.Exit(1)
}
switch enabled, err := features.Enabled(auth.FeatureGateObjectLevelWorkloadIdentity); {
case err != nil:
setupLog.Error(err, "unable to check feature gate "+auth.FeatureGateObjectLevelWorkloadIdentity)
os.Exit(1)
case enabled:
auth.EnableObjectLevelWorkloadIdentity()
}
if err := intervalJitterOptions.SetGlobalJitter(nil); err != nil {
setupLog.Error(err, "unable to set global jitter")
os.Exit(1)