@@ -19,9 +19,9 @@ package operatorchecker
19
19
import (
20
20
"context"
21
21
"strings"
22
+ "time"
22
23
23
24
olmv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
24
- "k8s.io/apimachinery/pkg/types"
25
25
"k8s.io/klog"
26
26
ctrl "sigs.k8s.io/controller-runtime"
27
27
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -37,54 +37,109 @@ type Reconciler struct {
37
37
38
38
// Reconcile watchs on the Subscription of the target namespace and apply the recovery to fixing the Subscription failed error
39
39
func (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 {
43
42
return ctrl.Result {}, client .IgnoreNotFound (err )
44
43
}
45
44
46
45
klog .V (2 ).Info ("Operator Checker is monitoring Subscription..." )
47
46
48
47
if _ , ok := subscriptionInstance .Labels [constant .OpreqLabel ]; ! ok {
49
- return
48
+ return ctrl. Result { RequeueAfter : constant . DefaultRequeueDuration }, nil
50
49
}
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 {
61
71
return ctrl.Result {}, client .IgnoreNotFound (err )
62
72
}
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 ]
63
88
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 )
80
98
}
81
99
}
82
- break
83
100
}
84
101
}
102
+
85
103
return ctrl.Result {RequeueAfter : constant .DefaultRequeueDuration }, nil
86
104
}
87
105
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
+
88
143
// SetupWithManager adds subscription to watch to the manager.
89
144
func (r * Reconciler ) SetupWithManager (mgr ctrl.Manager ) error {
90
145
return ctrl .NewControllerManagedBy (mgr ).
0 commit comments