@@ -36,6 +36,7 @@ import (
3636
3737 aclapis "github.com/fluxcd/pkg/apis/acl"
3838 "github.com/fluxcd/pkg/apis/meta"
39+ "github.com/fluxcd/pkg/auth"
3940 "github.com/fluxcd/pkg/runtime/acl"
4041 "github.com/fluxcd/pkg/runtime/conditions"
4142 "github.com/fluxcd/pkg/runtime/patch"
@@ -160,6 +161,151 @@ func TestImagePolicyReconciler_invalidImage(t *testing.T) {
160161 }).Should (BeTrue ())
161162}
162163
164+ func TestImagePolicyReconciler_objectLevelWorkloadIdentityFeatureGate (t * testing.T ) {
165+ t .Run ("disabled" , func (t * testing.T ) {
166+ g := NewWithT (t )
167+
168+ namespaceName := "imagepolicy-" + randStringRunes (5 )
169+ namespace := & corev1.Namespace {
170+ ObjectMeta : metav1.ObjectMeta {Name : namespaceName },
171+ }
172+ g .Expect (k8sClient .Create (ctx , namespace )).ToNot (HaveOccurred ())
173+ t .Cleanup (func () {
174+ g .Expect (k8sClient .Delete (ctx , namespace )).NotTo (HaveOccurred ())
175+ })
176+
177+ imageRepo := & imagev1.ImageRepository {
178+ ObjectMeta : metav1.ObjectMeta {
179+ Namespace : namespaceName ,
180+ Name : "repo" ,
181+ },
182+ Spec : imagev1.ImageRepositorySpec {
183+ Image : "ghcr.io/stefanprodan/podinfo" ,
184+ Provider : "aws" ,
185+ ServiceAccountName : "foo" ,
186+ },
187+ }
188+ g .Expect (k8sClient .Create (ctx , imageRepo )).NotTo (HaveOccurred ())
189+ t .Cleanup (func () {
190+ g .Expect (k8sClient .Delete (ctx , imageRepo )).NotTo (HaveOccurred ())
191+ })
192+
193+ g .Eventually (func () bool {
194+ err := k8sClient .Get (ctx , client .ObjectKeyFromObject (imageRepo ), imageRepo )
195+ return err == nil && conditions .IsStalled (imageRepo ) &&
196+ conditions .GetReason (imageRepo , meta .StalledCondition ) == meta .FeatureGateDisabledReason &&
197+ conditions .GetMessage (imageRepo , meta .StalledCondition ) == "to use spec.serviceAccountName for provider authentication please enable the ObjectLevelWorkloadIdentity feature gate in the controller"
198+ }).Should (BeTrue ())
199+
200+ g .Eventually (func () bool {
201+ p := patch .NewSerialPatcher (imageRepo , k8sClient )
202+ imageRepo .Spec .Suspend = true
203+ imageRepo .Status .Conditions = nil
204+ conditions .MarkTrue (imageRepo , meta .ReadyCondition , "success" , "image repository is ready" )
205+ return p .Patch (ctx , imageRepo ) == nil
206+ }).Should (BeTrue ())
207+
208+ imagePolicy := & imagev1.ImagePolicy {
209+ ObjectMeta : metav1.ObjectMeta {
210+ Namespace : namespaceName ,
211+ Name : "test-imagepolicy" ,
212+ },
213+ Spec : imagev1.ImagePolicySpec {
214+ ImageRepositoryRef : meta.NamespacedObjectReference {
215+ Name : imageRepo .Name ,
216+ },
217+ Policy : imagev1.ImagePolicyChoice {
218+ Alphabetical : & imagev1.AlphabeticalPolicy {},
219+ },
220+ },
221+ }
222+ g .Expect (k8sClient .Create (ctx , imagePolicy )).NotTo (HaveOccurred ())
223+ t .Cleanup (func () {
224+ g .Expect (k8sClient .Delete (ctx , imagePolicy )).NotTo (HaveOccurred ())
225+ })
226+
227+ g .Eventually (func () bool {
228+ err := k8sClient .Get (ctx , client .ObjectKeyFromObject (imagePolicy ), imagePolicy )
229+ logPolicyStatus (t , imagePolicy )
230+ return err == nil && conditions .IsStalled (imagePolicy ) &&
231+ conditions .GetReason (imagePolicy , meta .StalledCondition ) == meta .FeatureGateDisabledReason &&
232+ conditions .GetMessage (imagePolicy , meta .StalledCondition ) == "to use spec.serviceAccountName in the ImageRepository for provider authentication please enable the ObjectLevelWorkloadIdentity feature gate in the controller"
233+ }).Should (BeTrue ())
234+ })
235+
236+ t .Run ("enabled" , func (t * testing.T ) {
237+ g := NewWithT (t )
238+
239+ t .Setenv (auth .EnvVarEnableObjectLevelWorkloadIdentity , "true" )
240+
241+ namespaceName := "imagepolicy-" + randStringRunes (5 )
242+ namespace := & corev1.Namespace {
243+ ObjectMeta : metav1.ObjectMeta {Name : namespaceName },
244+ }
245+ g .Expect (k8sClient .Create (ctx , namespace )).ToNot (HaveOccurred ())
246+ t .Cleanup (func () {
247+ g .Expect (k8sClient .Delete (ctx , namespace )).NotTo (HaveOccurred ())
248+ })
249+
250+ imageRepo := & imagev1.ImageRepository {
251+ ObjectMeta : metav1.ObjectMeta {
252+ Namespace : namespaceName ,
253+ Name : "repo" ,
254+ },
255+ Spec : imagev1.ImageRepositorySpec {
256+ Image : "ghcr.io/stefanprodan/podinfo" ,
257+ Provider : "aws" ,
258+ ServiceAccountName : "foo" ,
259+ },
260+ }
261+ g .Expect (k8sClient .Create (ctx , imageRepo )).NotTo (HaveOccurred ())
262+ t .Cleanup (func () {
263+ g .Expect (k8sClient .Delete (ctx , imageRepo )).NotTo (HaveOccurred ())
264+ })
265+
266+ g .Eventually (func () bool {
267+ err := k8sClient .Get (ctx , client .ObjectKeyFromObject (imageRepo ), imageRepo )
268+ logRepoStatus (t , imageRepo )
269+ return err == nil && ! conditions .IsReady (imageRepo ) &&
270+ conditions .GetReason (imageRepo , meta .ReadyCondition ) == imagev1 .AuthenticationFailedReason
271+ }).Should (BeTrue ())
272+
273+ g .Eventually (func () bool {
274+ p := patch .NewSerialPatcher (imageRepo , k8sClient )
275+ imageRepo .Spec .Suspend = true
276+ imageRepo .Status .Conditions = nil
277+ conditions .MarkTrue (imageRepo , meta .ReadyCondition , "success" , "image repository is ready" )
278+ return p .Patch (ctx , imageRepo ) == nil
279+ }).Should (BeTrue ())
280+
281+ imagePolicy := & imagev1.ImagePolicy {
282+ ObjectMeta : metav1.ObjectMeta {
283+ Namespace : namespaceName ,
284+ Name : "test-imagepolicy" ,
285+ },
286+ Spec : imagev1.ImagePolicySpec {
287+ ImageRepositoryRef : meta.NamespacedObjectReference {
288+ Name : imageRepo .Name ,
289+ },
290+ Policy : imagev1.ImagePolicyChoice {
291+ Alphabetical : & imagev1.AlphabeticalPolicy {},
292+ },
293+ },
294+ }
295+ g .Expect (k8sClient .Create (ctx , imagePolicy )).NotTo (HaveOccurred ())
296+ t .Cleanup (func () {
297+ g .Expect (k8sClient .Delete (ctx , imagePolicy )).NotTo (HaveOccurred ())
298+ })
299+
300+ g .Eventually (func () bool {
301+ err := k8sClient .Get (ctx , client .ObjectKeyFromObject (imagePolicy ), imagePolicy )
302+ logPolicyStatus (t , imagePolicy )
303+ return err == nil && ! conditions .IsReady (imagePolicy ) &&
304+ conditions .GetReason (imagePolicy , meta .ReadyCondition ) == imagev1 .DependencyNotReadyReason
305+ }).Should (BeTrue ())
306+ })
307+ }
308+
163309func TestImagePolicyReconciler_intervalNotConfigured (t * testing.T ) {
164310 g := NewWithT (t )
165311
0 commit comments