@@ -19,9 +19,9 @@ package operatorchecker
1919import (
2020 "context"
2121 "strings"
22+ "time"
2223
2324 olmv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
24- "k8s.io/apimachinery/pkg/types"
2525 "k8s.io/klog"
2626 ctrl "sigs.k8s.io/controller-runtime"
2727 "sigs.k8s.io/controller-runtime/pkg/client"
@@ -37,54 +37,109 @@ type Reconciler struct {
3737
3838// Reconcile watchs on the Subscription of the target namespace and apply the recovery to fixing the Subscription failed error
3939func (r * Reconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (_ ctrl.Result , reconcileErr error ) {
40- // Fetch the subscription instance
41- subscriptionInstance := & olmv1alpha1.Subscription {}
42- if err := r .Client .Get (ctx , req .NamespacedName , subscriptionInstance ); err != nil {
40+ subscriptionInstance , err := r .getSubscription (ctx , req )
41+ if err != nil {
4342 return ctrl.Result {}, client .IgnoreNotFound (err )
4443 }
4544
4645 klog .V (2 ).Info ("Operator Checker is monitoring Subscription..." )
4746
4847 if _ , ok := subscriptionInstance .Labels [constant .OpreqLabel ]; ! ok {
49- return
48+ return ctrl. Result { RequeueAfter : constant . DefaultRequeueDuration }, nil
5049 }
51- if subscriptionInstance .Status .State != "" {
52- return
53- }
54- for _ , condition := range subscriptionInstance .Status .Conditions {
55- if condition .Type == "ResolutionFailed" && condition .Reason == "ConstraintsNotSatisfiable" {
56- csvList := & olmv1alpha1.ClusterServiceVersionList {}
57- opts := []client.ListOption {
58- client .InNamespace (subscriptionInstance .Namespace ),
59- }
60- if err := r .Client .List (ctx , csvList , opts ... ); err != nil {
50+
51+ if subscriptionInstance .Status .CurrentCSV == "" && subscriptionInstance .Status .State == "" {
52+ // cover fresh install case
53+ csvList , err := r .getCSVBySubscription (ctx , subscriptionInstance )
54+ if err != nil {
55+ klog .Error (err )
56+ return ctrl.Result {RequeueAfter : constant .DefaultRequeueDuration }, nil
57+ }
58+ if len (csvList ) != 1 {
59+ klog .Warning ("Not found matched CSV, CSVList length: " , len (csvList ))
60+ return ctrl.Result {RequeueAfter : constant .DefaultRequeueDuration }, nil
61+ }
62+ csv := csvList [0 ]
63+
64+ time .Sleep (constant .DefaultCSVWaitPeriod )
65+ subscriptionInstance , err := r .getSubscription (ctx , req )
66+ if err != nil {
67+ return ctrl.Result {}, client .IgnoreNotFound (err )
68+ }
69+ if subscriptionInstance .Status .CurrentCSV == "" && subscriptionInstance .Status .State == "" {
70+ if err = r .deleteCSV (ctx , csv .Name , csv .Namespace ); err != nil {
6171 return ctrl.Result {}, client .IgnoreNotFound (err )
6272 }
73+ }
74+ }
75+
76+ if subscriptionInstance .Status .CurrentCSV != "" && subscriptionInstance .Status .State == "UpgradePending" {
77+ // cover upgrade case
78+ csvList , err := r .getCSVBySubscription (ctx , subscriptionInstance )
79+ if err != nil {
80+ klog .Error (err )
81+ return ctrl.Result {RequeueAfter : constant .DefaultRequeueDuration }, nil
82+ }
83+ if len (csvList ) != 1 {
84+ klog .Warning ("Not found matched CSV, CSVList length: " , len (csvList ))
85+ return ctrl.Result {RequeueAfter : constant .DefaultRequeueDuration }, nil
86+ }
87+ csv := csvList [0 ]
6388
64- for _ , csv := range csvList .Items {
65- if strings .Contains (csv .Name , subscriptionInstance .Name ) {
66- if csv .Status .Phase == "Succeeded" {
67- csvInstance := & olmv1alpha1.ClusterServiceVersion {}
68- csvKey := types.NamespacedName {
69- Name : csv .Name ,
70- Namespace : csv .Namespace ,
71- }
72- if err := r .Client .Get (ctx , csvKey , csvInstance ); err != nil {
73- return ctrl.Result {}, client .IgnoreNotFound (err )
74- }
75- if err := r .Client .Delete (ctx , csvInstance ); err != nil {
76- return ctrl.Result {}, client .IgnoreNotFound (err )
77- }
78- }
79- break
89+ if subscriptionInstance .Status .CurrentCSV != csv .Spec .Version .String () {
90+ time .Sleep (constant .DefaultCSVWaitPeriod )
91+ subscriptionInstance , err := r .getSubscription (ctx , req )
92+ if err != nil {
93+ return ctrl.Result {}, client .IgnoreNotFound (err )
94+ }
95+ if subscriptionInstance .Status .CurrentCSV != "" && subscriptionInstance .Status .State == "UpgradePending" {
96+ if err = r .deleteCSV (ctx , csv .Name , csv .Namespace ); err != nil {
97+ return ctrl.Result {}, client .IgnoreNotFound (err )
8098 }
8199 }
82- break
83100 }
84101 }
102+
85103 return ctrl.Result {RequeueAfter : constant .DefaultRequeueDuration }, nil
86104}
87105
106+ func (r * Reconciler ) getCSVBySubscription (ctx context.Context , subscriptionInstance * olmv1alpha1.Subscription ) ([]olmv1alpha1.ClusterServiceVersion , error ) {
107+ csvList := & olmv1alpha1.ClusterServiceVersionList {}
108+ opts := []client.ListOption {
109+ client .InNamespace (subscriptionInstance .Namespace ),
110+ }
111+ if err := r .Client .List (ctx , csvList , opts ... ); err != nil {
112+ return nil , client .IgnoreNotFound (err )
113+ }
114+
115+ var matchCSVList = []olmv1alpha1.ClusterServiceVersion {}
116+ for _ , csv := range csvList .Items {
117+ if strings .Contains (csv .Name , subscriptionInstance .Name ) {
118+ matchCSVList = append (matchCSVList , csv )
119+ }
120+ }
121+ return matchCSVList , nil
122+ }
123+
124+ func (r * Reconciler ) getSubscription (ctx context.Context , req ctrl.Request ) (* olmv1alpha1.Subscription , error ) {
125+ // Fetch the subscription instance
126+ subscriptionInstance := & olmv1alpha1.Subscription {}
127+ if err := r .Client .Get (ctx , req .NamespacedName , subscriptionInstance ); err != nil {
128+ return nil , err
129+ }
130+ return subscriptionInstance , nil
131+ }
132+
133+ func (r * Reconciler ) deleteCSV (ctx context.Context , name , namespace string ) error {
134+ csvInstance := & olmv1alpha1.ClusterServiceVersion {}
135+ csvInstance .Name = name
136+ csvInstance .Namespace = namespace
137+ if err := r .Client .Delete (ctx , csvInstance ); err != nil {
138+ return client .IgnoreNotFound (err )
139+ }
140+ return nil
141+ }
142+
88143// SetupWithManager adds subscription to watch to the manager.
89144func (r * Reconciler ) SetupWithManager (mgr ctrl.Manager ) error {
90145 return ctrl .NewControllerManagedBy (mgr ).
0 commit comments