@@ -741,9 +741,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
741741 if err != nil {
742742 syncError = err
743743 logger .WithError (err ).Warn ("csv has invalid installmodes" )
744- if out .Status .Reason != v1alpha1 .CSVReasonInvalidInstallModes {
745- out .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonInvalidInstallModes , syncError .Error (), now , a .recorder )
746- }
744+ out .SetPhaseWithEventIfChanged (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonInvalidInstallModes , syncError .Error (), now , a .recorder )
747745 return
748746 }
749747
@@ -754,16 +752,12 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
754752
755753 if err := modeSet .Supports (out .GetNamespace (), namespaces ); err != nil {
756754 logger .WithField ("reason" , err .Error ()).Info ("installmodeset does not support operatorgroups namespace selection" )
757- if out .Status .Reason != v1alpha1 .CSVReasonUnsupportedOperatorGroup {
758- out .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonUnsupportedOperatorGroup , err .Error (), now , a .recorder )
759- }
755+ out .SetPhaseWithEventIfChanged (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonUnsupportedOperatorGroup , err .Error (), now , a .recorder )
760756 return
761757 }
762758 } else {
763759 logger .Info ("csv missing olm.targetNamespaces annotation" )
764- if out .Status .Reason != v1alpha1 .CSVReasonNoTargetNamespaces {
765- out .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonNoTargetNamespaces , "csv missing olm.targetNamespaces annotation" , now , a .recorder )
766- }
760+ out .SetPhaseWithEventIfChanged (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonNoTargetNamespaces , "csv missing olm.targetNamespaces annotation" , now , a .recorder )
767761 return
768762 }
769763
@@ -855,6 +849,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
855849 }
856850
857851 // Check for CRD ownership conflicts
852+ // TODO: find CSVs that provide any of those that out does across all namespaces
858853 csvSet := a .csvSet (out .GetNamespace (), v1alpha1 .CSVPhaseAny )
859854 if syncError = a .crdOwnerConflicts (out , csvSet ); syncError != nil {
860855 out .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonOwnerConflict , fmt .Sprintf ("crd owner conflict: %s" , syncError ), now , a .recorder )
@@ -893,6 +888,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
893888 a .Log .Warn (err .Error ())
894889 }
895890 return
891+
896892 case v1alpha1 .CSVPhaseInstalling :
897893 installer , strategy , _ := a .parseStrategiesAndUpdateStatus (out )
898894 if strategy == nil {
@@ -902,15 +898,22 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
902898 if installErr := a .updateInstallStatus (out , installer , strategy , v1alpha1 .CSVPhaseInstalling , v1alpha1 .CSVReasonWaiting ); installErr == nil {
903899 logger .WithField ("strategy" , out .Spec .InstallStrategy .StrategyName ).Infof ("install strategy successful" )
904900 }
901+
905902 case v1alpha1 .CSVPhaseSucceeded :
906903 installer , strategy , _ := a .parseStrategiesAndUpdateStatus (out )
907904 if strategy == nil {
908905 return
909906 }
910907
911- // Check install status
912- if installErr := a .updateInstallStatus (out , installer , strategy , v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonComponentUnhealthy ); installErr != nil {
913- logger .WithField ("strategy" , out .Spec .InstallStrategy .StrategyName ).Warnf ("unhealthy component: %s" , installErr )
908+ // Check if any generated resources are missing
909+ if err := a .checkAPIServiceResources (out , certs .PEMSHA256 ); err != nil {
910+ out .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonAPIServiceResourceIssue , err .Error (), now , a .recorder )
911+ return
912+ }
913+
914+ // Check if it's time to refresh owned APIService certs
915+ if a .shouldRotateCerts (out ) {
916+ out .SetPhaseWithEvent (v1alpha1 .CSVPhasePending , v1alpha1 .CSVReasonNeedsCertRotation , "owned APIServices need cert refresh" , now , a .recorder )
914917 return
915918 }
916919
@@ -926,15 +929,9 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
926929 return
927930 }
928931
929- // Check if any generated resources are missing
930- if resErr := a .checkAPIServiceResources (out , certs .PEMSHA256 ); len (resErr ) > 0 {
931- out .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonAPIServiceResourceIssue , resErr [0 ].Error (), now , a .recorder )
932- return
933- }
934-
935- // Check if it's time to refresh owned APIService certs
936- if a .shouldRotateCerts (out ) {
937- out .SetPhaseWithEvent (v1alpha1 .CSVPhasePending , v1alpha1 .CSVReasonNeedsCertRotation , "owned APIServices need cert refresh" , now , a .recorder )
932+ // Check install status
933+ if installErr := a .updateInstallStatus (out , installer , strategy , v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonComponentUnhealthy ); installErr != nil {
934+ logger .WithField ("strategy" , out .Spec .InstallStrategy .StrategyName ).Warnf ("unhealthy component: %s" , installErr )
938935 return
939936 }
940937
@@ -971,15 +968,9 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
971968 return
972969 }
973970
974- // Check install status
975- if installErr := a .updateInstallStatus (out , installer , strategy , v1alpha1 .CSVPhasePending , v1alpha1 .CSVReasonNeedsReinstall ); installErr != nil {
976- logger .WithField ("strategy" , out .Spec .InstallStrategy .StrategyName ).Warnf ("needs reinstall: %s" , installErr )
977- return
978- }
979-
980971 // Check if requirements exist
981972 met , statuses , err := a .requirementAndPermissionStatus (out )
982- if err != nil {
973+ if err != nil && out . Status . Reason != v1alpha1 . CSVReasonInvalidStrategy {
983974 logger .Warn ("invalid install strategy" )
984975 out .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonInvalidStrategy , fmt .Sprintf ("install strategy invalid: %s" , err .Error ()), now , a .recorder )
985976 return
@@ -989,20 +980,24 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
989980 return
990981 }
991982
992- // Check if any generated resources are missing
993- if resErr := a .checkAPIServiceResources (out , certs .PEMSHA256 ); len ( resErr ) > 0 {
983+ // Check if any generated resources are missing and that OLM can action on them
984+ if err := a .checkAPIServiceResources (out , certs .PEMSHA256 ); err != nil && a . apiServiceResourceErrorActionable ( err ) {
994985 // Check if API services are adoptable. If not, keep CSV as Failed state
995- if a .apiServiceResourceErrorsActionable (resErr ) {
996- out .SetPhaseWithEvent (v1alpha1 .CSVPhasePending , v1alpha1 .CSVReasonAPIServiceResourcesNeedReinstall , resErr [0 ].Error (), now , a .recorder )
997- return
998- }
986+ out .SetPhaseWithEvent (v1alpha1 .CSVPhasePending , v1alpha1 .CSVReasonAPIServiceResourcesNeedReinstall , err .Error (), now , a .recorder )
987+ return
999988 }
1000989
1001990 // Check if it's time to refresh owned APIService certs
1002991 if a .shouldRotateCerts (out ) {
1003992 out .SetPhaseWithEvent (v1alpha1 .CSVPhasePending , v1alpha1 .CSVReasonNeedsCertRotation , "owned APIServices need cert refresh" , now , a .recorder )
1004993 return
1005994 }
995+
996+ // Check install status
997+ if installErr := a .updateInstallStatus (out , installer , strategy , v1alpha1 .CSVPhasePending , v1alpha1 .CSVReasonNeedsReinstall ); installErr != nil {
998+ logger .WithField ("strategy" , out .Spec .InstallStrategy .StrategyName ).Warnf ("needs reinstall: %s" , installErr )
999+ }
1000+
10061001 case v1alpha1 .CSVPhaseReplacing :
10071002 // determine CSVs that are safe to delete by finding a replacement chain to a CSV that's running
10081003 // since we don't know what order we'll process replacements, we have to guard against breaking that chain
@@ -1109,41 +1104,38 @@ func (a *Operator) checkReplacementsAndUpdateStatus(csv *v1alpha1.ClusterService
11091104}
11101105
11111106func (a * Operator ) updateInstallStatus (csv * v1alpha1.ClusterServiceVersion , installer install.StrategyInstaller , strategy install.Strategy , requeuePhase v1alpha1.ClusterServiceVersionPhase , requeueConditionReason v1alpha1.ConditionReason ) error {
1112- apiServicesInstalled , apiServiceErr := a .areAPIServicesAvailable (csv . Spec . APIServiceDefinitions . Owned )
1107+ apiServicesInstalled , apiServiceErr := a .areAPIServicesAvailable (csv )
11131108 strategyInstalled , strategyErr := installer .CheckInstalled (strategy )
11141109 now := timeNow ()
11151110
11161111 if strategyInstalled && apiServicesInstalled {
11171112 // if there's no error, we're successfully running
1118- if csv .Status .Phase != v1alpha1 .CSVPhaseSucceeded {
1119- csv .SetPhaseWithEvent (v1alpha1 .CSVPhaseSucceeded , v1alpha1 .CSVReasonInstallSuccessful , "install strategy completed with no errors" , now , a .recorder )
1120- }
1113+ csv .SetPhaseWithEventIfChanged (v1alpha1 .CSVPhaseSucceeded , v1alpha1 .CSVReasonInstallSuccessful , "install strategy completed with no errors" , now , a .recorder )
11211114 return nil
11221115 }
11231116
11241117 // installcheck determined we can't progress (e.g. deployment failed to come up in time)
11251118 if install .IsErrorUnrecoverable (strategyErr ) {
1126- csv .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonInstallCheckFailed , fmt .Sprintf ("install failed: %s" , strategyErr ), now , a .recorder )
1119+ csv .SetPhaseWithEventIfChanged (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonInstallCheckFailed , fmt .Sprintf ("install failed: %s" , strategyErr ), now , a .recorder )
11271120 return strategyErr
11281121 }
11291122
11301123 if apiServiceErr != nil {
1131- csv .SetPhaseWithEvent (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonAPIServiceInstallFailed , fmt .Sprintf ("APIService install failed: %s" , apiServiceErr ), now , a .recorder )
1124+ csv .SetPhaseWithEventIfChanged (v1alpha1 .CSVPhaseFailed , v1alpha1 .CSVReasonAPIServiceInstallFailed , fmt .Sprintf ("APIService install failed: %s" , apiServiceErr ), now , a .recorder )
11321125 return apiServiceErr
11331126 }
11341127
11351128 if ! apiServicesInstalled {
1136- csv .SetPhaseWithEvent (requeuePhase , requeueConditionReason , fmt .Sprintf ("APIServices not installed" ), now , a .recorder )
1137- err := a .csvQueueSet .Requeue (csv .GetName (), csv .GetNamespace ())
1138- if err != nil {
1129+ csv .SetPhaseWithEventIfChanged (requeuePhase , requeueConditionReason , fmt .Sprintf ("APIServices not installed" ), now , a .recorder )
1130+ if err := a .csvQueueSet .Requeue (csv .GetName (), csv .GetNamespace ()); err != nil {
11391131 a .Log .Warn (err .Error ())
11401132 }
11411133
11421134 return fmt .Errorf ("APIServices not installed" )
11431135 }
11441136
11451137 if strategyErr != nil {
1146- csv .SetPhaseWithEvent (requeuePhase , requeueConditionReason , fmt .Sprintf ("installing: %s" , strategyErr ), now , a .recorder )
1138+ csv .SetPhaseWithEventIfChanged (requeuePhase , requeueConditionReason , fmt .Sprintf ("installing: %s" , strategyErr ), now , a .recorder )
11471139 return strategyErr
11481140 }
11491141
@@ -1178,23 +1170,20 @@ func (a *Operator) parseStrategiesAndUpdateStatus(csv *v1alpha1.ClusterServiceVe
11781170}
11791171
11801172func (a * Operator ) crdOwnerConflicts (in * v1alpha1.ClusterServiceVersion , csvsInNamespace map [string ]* v1alpha1.ClusterServiceVersion ) error {
1181- owned := false
11821173 for _ , crd := range in .Spec .CustomResourceDefinitions .Owned {
11831174 for csvName , csv := range csvsInNamespace {
11841175 if csvName == in .GetName () {
11851176 continue
11861177 }
11871178 if csv .OwnsCRD (crd .Name ) {
1188- owned = true
1189- }
1190- if owned && in . Spec . Replaces == csvName {
1191- return nil
1179+ if in . Spec . Replaces == csvName {
1180+ return nil
1181+ }
1182+ return ErrCRDOwnerConflict
11921183 }
11931184 }
11941185 }
1195- if owned {
1196- return ErrCRDOwnerConflict
1197- }
1186+
11981187 return nil
11991188}
12001189
0 commit comments