@@ -28,6 +28,7 @@ import (
2828 "github.com/operator-framework/operator-registry/alpha/declcfg"
2929
3030 ocv1 "github.com/operator-framework/operator-controller/api/v1"
31+ "github.com/operator-framework/operator-controller/internal/authentication"
3132 "github.com/operator-framework/operator-controller/internal/conditionsets"
3233 "github.com/operator-framework/operator-controller/internal/controllers"
3334 "github.com/operator-framework/operator-controller/internal/finalizers"
@@ -332,6 +333,59 @@ func TestClusterExtensionResolutionAndUnpackSuccessfulApplierFails(t *testing.T)
332333 require .NoError (t , cl .DeleteAllOf (ctx , & ocv1.ClusterExtension {}))
333334}
334335
336+ func TestClusterExtensionServiceAccountNotFound (t * testing.T ) {
337+ cl , reconciler := newClientAndReconciler (t , func (r * controllers.ClusterExtensionReconciler ) {
338+ r .InstalledBundleGetter = & MockInstalledBundleGetter {
339+ err : & authentication.ServiceAccountNotFoundError {}, // Simulate missing SA
340+ }
341+ })
342+
343+ ctx := context .Background ()
344+ extKey := types.NamespacedName {Name : fmt .Sprintf ("cluster-extension-test-%s" , rand .String (8 ))}
345+
346+ t .Log ("Given a cluster extension with a missing service account" )
347+ clusterExtension := & ocv1.ClusterExtension {
348+ ObjectMeta : metav1.ObjectMeta {Name : extKey .Name },
349+ Spec : ocv1.ClusterExtensionSpec {
350+ Source : ocv1.SourceConfig {
351+ SourceType : "Catalog" ,
352+ Catalog : & ocv1.CatalogSource {
353+ PackageName : "test-package" ,
354+ },
355+ },
356+ Namespace : "default" ,
357+ ServiceAccount : ocv1.ServiceAccountReference {
358+ Name : "missing-sa" ,
359+ },
360+ },
361+ }
362+
363+ require .NoError (t , cl .Create (ctx , clusterExtension ))
364+
365+ t .Log ("When reconciling the cluster extension" )
366+ res , err := reconciler .Reconcile (ctx , ctrl.Request {NamespacedName : extKey })
367+
368+ require .Equal (t , ctrl.Result {}, res )
369+ require .Error (t , err )
370+ require .IsType (t , & authentication.ServiceAccountNotFoundError {}, err )
371+ t .Log ("By fetching updated cluster extension after reconcile" )
372+ require .NoError (t , cl .Get (ctx , extKey , clusterExtension ))
373+
374+ t .Log ("By checking the status conditions" )
375+ installedCond := apimeta .FindStatusCondition (clusterExtension .Status .Conditions , ocv1 .TypeInstalled )
376+ require .NotNil (t , installedCond )
377+ require .Equal (t , metav1 .ConditionUnknown , installedCond .Status )
378+ require .Contains (t , installedCond .Message , "unable to authenticate with the Kubernetes cluster" )
379+
380+ progressingCond := apimeta .FindStatusCondition (clusterExtension .Status .Conditions , ocv1 .TypeProgressing )
381+ require .NotNil (t , progressingCond )
382+ require .Equal (t , metav1 .ConditionTrue , progressingCond .Status )
383+ require .Equal (t , ocv1 .ReasonRetrying , progressingCond .Reason )
384+ require .Contains (t , progressingCond .Message , "installation cannot proceed due to missing ServiceAccount" )
385+
386+ require .NoError (t , cl .DeleteAllOf (ctx , & ocv1.ClusterExtension {}))
387+ }
388+
335389func TestClusterExtensionApplierFailsWithBundleInstalled (t * testing.T ) {
336390 cl , reconciler := newClientAndReconciler (t )
337391 reconciler .Unpacker = & MockUnpacker {
0 commit comments