Skip to content

Commit e8bf8f8

Browse files
committed
[RFC-0010] Introduce feature gate
Signed-off-by: Matheus Pimenta <[email protected]>
1 parent 0058004 commit e8bf8f8

File tree

9 files changed

+116
-18
lines changed

9 files changed

+116
-18
lines changed

api/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.24.0
44

55
require (
66
github.com/fluxcd/pkg/apis/acl v0.7.0
7-
github.com/fluxcd/pkg/apis/meta v1.11.0
7+
github.com/fluxcd/pkg/apis/meta v1.12.0
88
k8s.io/apimachinery v0.33.0
99
sigs.k8s.io/controller-runtime v0.20.4
1010
)

api/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
55
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
66
github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0=
77
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
8-
github.com/fluxcd/pkg/apis/meta v1.11.0 h1:h8q95k6ZEK1HCfsLkt8Np3i6ktb6ZzcWJ6hg++oc9w0=
9-
github.com/fluxcd/pkg/apis/meta v1.11.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
8+
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
9+
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
1010
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
1111
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
1212
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ require (
2323
github.com/elazarl/goproxy v1.7.2
2424
github.com/fluxcd/cli-utils v0.36.0-flux.13
2525
github.com/fluxcd/pkg/apis/event v0.17.0
26-
github.com/fluxcd/pkg/apis/meta v1.11.0
27-
github.com/fluxcd/pkg/auth v0.12.0
26+
github.com/fluxcd/pkg/apis/meta v1.12.0
27+
github.com/fluxcd/pkg/auth v0.13.0
2828
github.com/fluxcd/pkg/cache v0.9.0
29-
github.com/fluxcd/pkg/git v0.29.0
30-
github.com/fluxcd/pkg/git/gogit v0.31.0
29+
github.com/fluxcd/pkg/git v0.30.0
30+
github.com/fluxcd/pkg/git/gogit v0.32.0
3131
github.com/fluxcd/pkg/gittestserver v0.17.0
3232
github.com/fluxcd/pkg/helmtestserver v0.24.0
3333
github.com/fluxcd/pkg/lockedfile v0.6.0

go.sum

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -372,16 +372,16 @@ github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5o
372372
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
373373
github.com/fluxcd/pkg/apis/event v0.17.0 h1:foEINE++pCJlWVhWjYDXfkVmGKu8mQ4BDBlbYi5NU7M=
374374
github.com/fluxcd/pkg/apis/event v0.17.0/go.mod h1:0fLhLFiHlRTDKPDXdRnv+tS7mCMIQ0fJxnEfmvGM/5A=
375-
github.com/fluxcd/pkg/apis/meta v1.11.0 h1:h8q95k6ZEK1HCfsLkt8Np3i6ktb6ZzcWJ6hg++oc9w0=
376-
github.com/fluxcd/pkg/apis/meta v1.11.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
377-
github.com/fluxcd/pkg/auth v0.12.0 h1:35o0ziYMLZVgJwNvJBGsv/wd903B2fMagcrnm1ptUjc=
378-
github.com/fluxcd/pkg/auth v0.12.0/go.mod h1:gQD2VT5OhIR1E8ZTEsTaho3bDQZidr9P10smH/awcew=
375+
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
376+
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
377+
github.com/fluxcd/pkg/auth v0.13.0 h1:CLJJk+NPrCIDs1yPqdwAvNLwFBaogum2XJLI4TD2gr4=
378+
github.com/fluxcd/pkg/auth v0.13.0/go.mod h1:gQD2VT5OhIR1E8ZTEsTaho3bDQZidr9P10smH/awcew=
379379
github.com/fluxcd/pkg/cache v0.9.0 h1:EGKfOLMG3fOwWnH/4Axl5xd425mxoQbZzlZoLfd8PDk=
380380
github.com/fluxcd/pkg/cache v0.9.0/go.mod h1:jMwabjWfsC5lW8hE7NM3wtGNwSJ38Javx6EKbEi7INU=
381-
github.com/fluxcd/pkg/git v0.29.0 h1:MHQ4F53e6Xt8a/POkd/fiChgysnd/XqiuK7vOWXAXLk=
382-
github.com/fluxcd/pkg/git v0.29.0/go.mod h1:Ygn+LfrK6Ok+85uiq6s3NWG5LcHS4KY7mzES2JDJsGY=
383-
github.com/fluxcd/pkg/git/gogit v0.31.0 h1:A56cmtgJBkWAj+gXSOdhPMQVTx0VF91S0PUaqpMXN4g=
384-
github.com/fluxcd/pkg/git/gogit v0.31.0/go.mod h1:ya8z22xTvAAdW12HycxKYv4S+G+lqu5Kx/LyO/jWz8Y=
381+
github.com/fluxcd/pkg/git v0.30.0 h1:jwc67whpwSvDJTo+GS1pW1fZsx/VVjhiSWfWeWxbqQM=
382+
github.com/fluxcd/pkg/git v0.30.0/go.mod h1:8nrHf1RrExQsJfR7ihErv2UpFaKy0zrcUzkXlQ+7pZs=
383+
github.com/fluxcd/pkg/git/gogit v0.32.0 h1:sm8dO9UuUHO5zJRj0GJ7WQnqHvEzolpBFge0y2V16mA=
384+
github.com/fluxcd/pkg/git/gogit v0.32.0/go.mod h1:xjtCSqV53VNCSjs5CXp8Qo3AFGyYD9V4r3GFTXU+O18=
385385
github.com/fluxcd/pkg/gittestserver v0.17.0 h1:JlBvWZQTDOI+np5Z+084m3DkeAH1hMusEybyRUDF63k=
386386
github.com/fluxcd/pkg/gittestserver v0.17.0/go.mod h1:E/40EmLoXcMqd6gLuLDC9F6KJxqHVGbBBeMNKk5XdxU=
387387
github.com/fluxcd/pkg/helmtestserver v0.24.0 h1:9sSfRG17GnDIup4sI8V+fdvKROtunU4JyIo34uvXq3Q=

internal/controller/ocirepository_controller.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,13 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
369369
if _, ok := keychain.(soci.Anonymous); obj.Spec.Provider != ociv1.GenericOCIProvider && ok {
370370
var opts []auth.Option
371371
if obj.Spec.ServiceAccountName != "" {
372+
// Check object-level workload identity feature gate.
373+
if !auth.IsObjectLevelWorkloadIdentityEnabled() {
374+
const gate = auth.FeatureGateObjectLevelWorkloadIdentity
375+
const msgFmt = "to use spec.serviceAccountName for provider authentication please enable the %s feature gate in the controller"
376+
err := fmt.Errorf(msgFmt, gate)
377+
return sreconcile.ResultEmpty, serror.NewStalling(err, meta.FeatureGateDisabledReason)
378+
}
372379
serviceAccount := client.ObjectKey{
373380
Name: obj.Spec.ServiceAccountName,
374381
Namespace: obj.GetNamespace(),

internal/controller/ocirepository_controller_test.go

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import (
6060

6161
kstatus "github.com/fluxcd/cli-utils/pkg/kstatus/status"
6262
"github.com/fluxcd/pkg/apis/meta"
63+
"github.com/fluxcd/pkg/auth"
6364
"github.com/fluxcd/pkg/git"
6465
"github.com/fluxcd/pkg/oci"
6566
"github.com/fluxcd/pkg/runtime/conditions"
@@ -2971,10 +2972,10 @@ func TestOCIRepository_getArtifactRef(t *testing.T) {
29712972
}
29722973
}
29732974

2974-
func TestOCIRepository_stalled(t *testing.T) {
2975+
func TestOCIRepository_invalidURL(t *testing.T) {
29752976
g := NewWithT(t)
29762977

2977-
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-stalled-test")
2978+
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-invalid-url-test")
29782979
g.Expect(err).ToNot(HaveOccurred())
29792980
defer func() { g.Expect(testEnv.Delete(ctx, ns)).To(Succeed()) }()
29802981

@@ -3013,6 +3014,74 @@ func TestOCIRepository_stalled(t *testing.T) {
30133014
g.Expect(stalledCondition.Reason).Should(Equal(sourcev1.URLInvalidReason))
30143015
}
30153016

3017+
func TestOCIRepository_objectLevelWorkloadIdentityFeatureGate(t *testing.T) {
3018+
g := NewWithT(t)
3019+
3020+
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-olwifg-test")
3021+
g.Expect(err).ToNot(HaveOccurred())
3022+
defer func() { g.Expect(testEnv.Delete(ctx, ns)).To(Succeed()) }()
3023+
3024+
err = testEnv.Create(ctx, &corev1.ServiceAccount{
3025+
ObjectMeta: metav1.ObjectMeta{
3026+
Namespace: ns.Name,
3027+
Name: "test",
3028+
},
3029+
})
3030+
g.Expect(err).NotTo(HaveOccurred())
3031+
3032+
obj := &ociv1.OCIRepository{
3033+
ObjectMeta: metav1.ObjectMeta{
3034+
GenerateName: "ocirepository-reconcile",
3035+
Namespace: ns.Name,
3036+
},
3037+
Spec: ociv1.OCIRepositorySpec{
3038+
URL: "oci://ghcr.io/stefanprodan/manifests/podinfo",
3039+
Interval: metav1.Duration{Duration: 60 * time.Minute},
3040+
Provider: "aws",
3041+
ServiceAccountName: "test",
3042+
},
3043+
}
3044+
3045+
g.Expect(testEnv.Create(ctx, obj)).To(Succeed())
3046+
3047+
key := client.ObjectKey{Name: obj.Name, Namespace: obj.Namespace}
3048+
resultobj := &ociv1.OCIRepository{}
3049+
3050+
g.Eventually(func() bool {
3051+
if err := testEnv.Get(ctx, key, resultobj); err != nil {
3052+
return false
3053+
}
3054+
return conditions.IsStalled(resultobj)
3055+
}).Should(BeTrue())
3056+
3057+
stalledCondition := conditions.Get(resultobj, meta.StalledCondition)
3058+
g.Expect(stalledCondition).ToNot(BeNil())
3059+
g.Expect(stalledCondition.Reason).Should(Equal(meta.FeatureGateDisabledReason))
3060+
g.Expect(stalledCondition.Message).Should(Equal("to use spec.serviceAccountName for provider authentication please enable the ObjectLevelWorkloadIdentity feature gate in the controller"))
3061+
3062+
t.Setenv(auth.EnvVarEnableObjectLevelWorkloadIdentity, "true")
3063+
3064+
g.Eventually(func() bool {
3065+
if err := testEnv.Get(ctx, key, resultobj); err != nil {
3066+
return false
3067+
}
3068+
resultobj.Annotations = map[string]string{
3069+
meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339),
3070+
}
3071+
return testEnv.Update(ctx, resultobj) == nil
3072+
}).Should(BeTrue())
3073+
3074+
g.Expect(testEnv.Update(ctx, resultobj)).To(Succeed())
3075+
g.Eventually(func() bool {
3076+
if err := testEnv.Get(ctx, key, resultobj); err != nil {
3077+
return false
3078+
}
3079+
logOCIRepoStatus(t, resultobj)
3080+
return !conditions.IsReady(resultobj) &&
3081+
conditions.GetReason(resultobj, meta.ReadyCondition) == sourcev1.AuthenticationFailedReason
3082+
}).Should(BeTrue())
3083+
}
3084+
30163085
func TestOCIRepository_reconcileStorage(t *testing.T) {
30173086
tests := []struct {
30183087
name string

internal/controller/suite_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import (
4343
"k8s.io/client-go/tools/record"
4444
ctrl "sigs.k8s.io/controller-runtime"
4545
"sigs.k8s.io/controller-runtime/pkg/client"
46+
"sigs.k8s.io/yaml"
4647

4748
"github.com/distribution/distribution/v3/configuration"
4849
dockerRegistry "github.com/distribution/distribution/v3/registry"
@@ -452,3 +453,8 @@ func randStringRunes(n int) string {
452453
func int64p(i int64) *int64 {
453454
return &i
454455
}
456+
457+
func logOCIRepoStatus(t *testing.T, obj *sourcev1beta2.OCIRepository) {
458+
sts, _ := yaml.Marshal(obj.Status)
459+
t.Log(string(sts))
460+
}

internal/features/features.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ limitations under the License.
1919
// states.
2020
package features
2121

22-
import feathelper "github.com/fluxcd/pkg/runtime/features"
22+
import (
23+
"github.com/fluxcd/pkg/auth"
24+
feathelper "github.com/fluxcd/pkg/runtime/features"
25+
)
2326

2427
const (
2528
// CacheSecretsAndConfigMaps controls whether secrets and configmaps should be cached.
@@ -35,6 +38,10 @@ var features = map[string]bool{
3538
CacheSecretsAndConfigMaps: false,
3639
}
3740

41+
func init() {
42+
auth.SetFeatureGates(features)
43+
}
44+
3845
// FeatureGates contains a list of all supported feature gates and
3946
// their default values.
4047
func FeatureGates() map[string]bool {

main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
4040
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
4141

42+
"github.com/fluxcd/pkg/auth"
4243
pkgcache "github.com/fluxcd/pkg/cache"
4344
"github.com/fluxcd/pkg/git"
4445
"github.com/fluxcd/pkg/runtime/client"
@@ -178,6 +179,14 @@ func main() {
178179
os.Exit(1)
179180
}
180181

182+
switch enabled, err := features.Enabled(auth.FeatureGateObjectLevelWorkloadIdentity); {
183+
case err != nil:
184+
setupLog.Error(err, "unable to check feature gate "+auth.FeatureGateObjectLevelWorkloadIdentity)
185+
os.Exit(1)
186+
case enabled:
187+
auth.EnableObjectLevelWorkloadIdentity()
188+
}
189+
181190
if err := intervalJitterOptions.SetGlobalJitter(nil); err != nil {
182191
setupLog.Error(err, "unable to set global jitter")
183192
os.Exit(1)

0 commit comments

Comments
 (0)