@@ -18,6 +18,7 @@ package controllers
18
18
19
19
import (
20
20
"context"
21
+ "fmt"
21
22
22
23
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
23
24
"k8s.io/apimachinery/pkg/api/equality"
@@ -26,6 +27,7 @@ import (
26
27
"k8s.io/apimachinery/pkg/runtime"
27
28
"k8s.io/apimachinery/pkg/types"
28
29
utilerrors "k8s.io/apimachinery/pkg/util/errors"
30
+ "k8s.io/utils/pointer"
29
31
ctrl "sigs.k8s.io/controller-runtime"
30
32
"sigs.k8s.io/controller-runtime/pkg/client"
31
33
"sigs.k8s.io/controller-runtime/pkg/log"
@@ -38,23 +40,13 @@ import (
38
40
// OperatorReconciler reconciles a Operator object
39
41
type OperatorReconciler struct {
40
42
client.Client
41
- Scheme * runtime.Scheme
42
-
43
- resolver * resolution.OperatorResolver
44
- }
45
-
46
- func NewOperatorReconciler (c client.Client , s * runtime.Scheme , r * resolution.OperatorResolver ) * OperatorReconciler {
47
- return & OperatorReconciler {
48
- Client : c ,
49
- Scheme : s ,
50
- resolver : r ,
51
- }
43
+ Scheme * runtime.Scheme
44
+ Resolver * resolution.OperatorResolver
52
45
}
53
46
54
- //+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators,verbs=get;list;watch;create;update;patch;delete
47
+ //+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators,verbs=get;list;watch
55
48
//+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators/status,verbs=get;update;patch
56
49
//+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators/finalizers,verbs=update
57
-
58
50
//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments,verbs=get;list;watch;create;update;patch
59
51
60
52
// Reconcile is part of the main kubernetes reconciliation loop which aims to
@@ -112,61 +104,102 @@ func checkForUnexpectedFieldChange(a, b operatorsv1alpha1.Operator) bool {
112
104
113
105
// Helper function to do the actual reconcile
114
106
func (r * OperatorReconciler ) reconcile (ctx context.Context , op * operatorsv1alpha1.Operator ) (ctrl.Result , error ) {
115
- // define condition parameters
116
- var status = metav1 .ConditionTrue
117
- var reason = operatorsv1alpha1 .ReasonResolutionSucceeded
118
- var message = "resolution was successful"
119
107
120
108
// run resolution
121
- solution , err := r .resolver .Resolve (ctx )
109
+ solution , err := r .Resolver .Resolve (ctx )
122
110
if err != nil {
123
- status = metav1 .ConditionTrue
124
- reason = operatorsv1alpha1 .ReasonResolutionFailed
125
- message = err .Error ()
126
- } else {
127
- // extract package bundle path from resolved variable
128
- for _ , variable := range solution .SelectedVariables () {
129
- switch v := variable .(type ) {
130
- case * bundles_and_dependencies.BundleVariable :
131
- packageName , err := v .BundleEntity ().PackageName ()
111
+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
112
+ Type : operatorsv1alpha1 .TypeReady ,
113
+ Status : metav1 .ConditionFalse ,
114
+ Reason : operatorsv1alpha1 .ReasonResolutionFailed ,
115
+ Message : err .Error (),
116
+ ObservedGeneration : op .GetGeneration (),
117
+ })
118
+ return ctrl.Result {}, nil
119
+ }
120
+
121
+ // extract package bundle path from resolved variable
122
+ packageFound := false
123
+ for _ , variable := range solution .SelectedVariables () {
124
+ switch v := variable .(type ) {
125
+ case * bundles_and_dependencies.BundleVariable :
126
+ packageName , err := v .BundleEntity ().PackageName ()
127
+ if err != nil {
128
+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
129
+ Type : operatorsv1alpha1 .TypeReady ,
130
+ Status : metav1 .ConditionFalse ,
131
+ Reason : operatorsv1alpha1 .ReasonBundleLookupFailed ,
132
+ Message : err .Error (),
133
+ ObservedGeneration : op .GetGeneration (),
134
+ })
135
+ return ctrl.Result {}, err
136
+ }
137
+ if packageName == op .Spec .PackageName {
138
+ bundlePath , err := v .BundleEntity ().BundlePath ()
132
139
if err != nil {
140
+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
141
+ Type : operatorsv1alpha1 .TypeReady ,
142
+ Status : metav1 .ConditionFalse ,
143
+ Reason : operatorsv1alpha1 .ReasonBundleLookupFailed ,
144
+ Message : err .Error (),
145
+ ObservedGeneration : op .GetGeneration (),
146
+ })
133
147
return ctrl.Result {}, err
134
148
}
135
- if packageName == op .Spec .PackageName {
136
- bundlePath , err := v .BundleEntity ().BundlePath ()
137
- if err != nil {
138
- return ctrl.Result {}, err
139
- }
140
- dep , err := r .generateExpectedBundleDeployment (* op , bundlePath )
141
- if err != nil {
142
- return ctrl.Result {}, err
143
- }
144
- // Create bundleDeployment if not found or Update if needed
145
- if err := r .ensureBundleDeployment (ctx , dep ); err != nil {
146
- return ctrl.Result {}, err
147
- }
148
- break
149
+ dep := r .generateExpectedBundleDeployment (* op , bundlePath )
150
+ // Create bundleDeployment if not found or Update if needed
151
+ if err := r .ensureBundleDeployment (ctx , dep ); err != nil {
152
+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
153
+ Type : operatorsv1alpha1 .TypeReady ,
154
+ Status : metav1 .ConditionFalse ,
155
+ Reason : operatorsv1alpha1 .ReasonBundleDeploymentFailed ,
156
+ Message : err .Error (),
157
+ ObservedGeneration : op .GetGeneration (),
158
+ })
159
+ return ctrl.Result {}, err
149
160
}
161
+ packageFound = true
162
+ break
150
163
}
151
164
}
152
165
}
166
+ if ! packageFound {
167
+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
168
+ Type : operatorsv1alpha1 .TypeReady ,
169
+ Status : metav1 .ConditionFalse ,
170
+ Reason : operatorsv1alpha1 .ReasonBundleLookupFailed ,
171
+ Message : fmt .Sprintf ("resolved set does not contain expected package %q" , op .Spec .PackageName ),
172
+ ObservedGeneration : op .GetGeneration (),
173
+ })
174
+ }
153
175
154
176
// update operator status
155
177
apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
156
178
Type : operatorsv1alpha1 .TypeReady ,
157
- Status : status ,
158
- Reason : reason ,
159
- Message : message ,
179
+ Status : metav1 . ConditionTrue ,
180
+ Reason : operatorsv1alpha1 . ReasonResolutionSucceeded ,
181
+ Message : "resolution was successful" ,
160
182
ObservedGeneration : op .GetGeneration (),
161
183
})
162
184
163
185
return ctrl.Result {}, nil
164
186
}
165
187
166
- func (r * OperatorReconciler ) generateExpectedBundleDeployment (o operatorsv1alpha1.Operator , bundlePath string ) (* rukpakv1alpha1.BundleDeployment , error ) {
167
- dep := & rukpakv1alpha1.BundleDeployment {
188
+ func (r * OperatorReconciler ) generateExpectedBundleDeployment (o operatorsv1alpha1.Operator , bundlePath string ) * rukpakv1alpha1.BundleDeployment {
189
+ // TODO: Use unstructured + server side apply?
190
+ return & rukpakv1alpha1.BundleDeployment {
168
191
ObjectMeta : metav1.ObjectMeta {
169
192
Name : o .GetName (),
193
+ OwnerReferences : []metav1.OwnerReference {
194
+ {
195
+ APIVersion : operatorsv1alpha1 .GroupVersion .String (),
196
+ Kind : "Operator" ,
197
+ Name : o .Name ,
198
+ UID : o .UID ,
199
+ Controller : pointer .Bool (true ),
200
+ BlockOwnerDeletion : pointer .Bool (true ),
201
+ },
202
+ },
170
203
},
171
204
Spec : rukpakv1alpha1.BundleDeploymentSpec {
172
205
//TODO: Don't assume plain provisioner
@@ -193,11 +226,6 @@ func (r *OperatorReconciler) generateExpectedBundleDeployment(o operatorsv1alpha
193
226
},
194
227
},
195
228
}
196
-
197
- if err := ctrl .SetControllerReference (& o , dep , r .Scheme ); err != nil {
198
- return nil , err
199
- }
200
- return dep , nil
201
229
}
202
230
203
231
// SetupWithManager sets up the controller with the Manager.
@@ -224,6 +252,9 @@ func (r *OperatorReconciler) ensureBundleDeployment(ctx context.Context, desired
224
252
}
225
253
226
254
// Check if the existing bundleDeployment's spec needs to be updated
255
+ //
256
+ // FIXME: checking only for spec differences means that we will not fixup
257
+ // changes to and removals of desired metadata.
227
258
if equality .Semantic .DeepEqual (existingBundleDeployment .Spec , desiredBundleDeployment .Spec ) {
228
259
return nil
229
260
}
0 commit comments