@@ -127,14 +127,14 @@ func (r *ExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alpha1.Ext
127
127
if ! features .OperatorControllerFeatureGate .Enabled (features .EnableExtensionAPI ) {
128
128
l .Info ("extension feature is gated" , "name" , ext .GetName (), "namespace" , ext .GetNamespace ())
129
129
130
- // Set the TypeInstalled condition to Unknown to indicate that the resolution
130
+ // Set the TypeInstalled condition to Failed to indicate that the resolution
131
131
// hasn't been attempted yet, due to the spec being invalid.
132
132
ext .Status .InstalledBundle = nil
133
- setInstalledStatusConditionUnknown (& ext .Status .Conditions , "extension feature is disabled" , ext .GetGeneration ())
134
- // Set the TypeResolved condition to Unknown to indicate that the resolution
133
+ setInstalledStatusConditionFailed (& ext .Status .Conditions , "extension feature is disabled" , ext .GetGeneration ())
134
+ // Set the TypeResolved condition to Failed to indicate that the resolution
135
135
// hasn't been attempted yet, due to the spec being invalid.
136
136
ext .Status .ResolvedBundle = nil
137
- setResolvedStatusConditionUnknown (& ext .Status .Conditions , "extension feature is disabled" , ext .GetGeneration ())
137
+ setResolvedStatusConditionFailed (& ext .Status .Conditions , "extension feature is disabled" , ext .GetGeneration ())
138
138
139
139
setDeprecationStatusesUnknown (& ext .Status .Conditions , "extension feature is disabled" , ext .GetGeneration ())
140
140
return ctrl.Result {}, nil
@@ -150,8 +150,10 @@ func (r *ExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alpha1.Ext
150
150
// TODO: Improve the resolution logic.
151
151
bundle , err := r .resolve (ctx , * ext )
152
152
if err != nil {
153
- ext .Status .InstalledBundle = nil
154
- setInstalledStatusConditionUnknown (& ext .Status .Conditions , "installation has not been attempted as resolution failed" , ext .GetGeneration ())
153
+ if c := apimeta .FindStatusCondition (ext .Status .Conditions , ocv1alpha1 .TypeInstalled ); c == nil {
154
+ ext .Status .InstalledBundle = nil
155
+ setInstalledStatusConditionFailed (& ext .Status .Conditions , "installation has not been attempted as resolution failed" , ext .GetGeneration ())
156
+ }
155
157
ext .Status .ResolvedBundle = nil
156
158
setResolvedStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
157
159
setDeprecationStatusesUnknown (& ext .Status .Conditions , "deprecation checks have not been attempted as resolution failed" , ext .GetGeneration ())
@@ -162,35 +164,47 @@ func (r *ExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alpha1.Ext
162
164
ext .Status .ResolvedBundle = bundleMetadataFor (bundle )
163
165
setResolvedStatusConditionSuccess (& ext .Status .Conditions , fmt .Sprintf ("resolved to %q" , bundle .Image ), ext .GetGeneration ())
164
166
167
+ // Populate the deprecation status using the resolved bundle
168
+ SetDeprecationStatusInExtension (ext , bundle )
169
+
165
170
mediaType , err := bundle .MediaType ()
166
171
if err != nil {
167
- setInstalledStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
168
- setDeprecationStatusesUnknown (& ext .Status .Conditions , "deprecation checks have not been attempted as installation has failed" , ext .GetGeneration ())
172
+ if c := apimeta .FindStatusCondition (ext .Status .Conditions , ocv1alpha1 .TypeInstalled ); c == nil {
173
+ ext .Status .InstalledBundle = nil
174
+ setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("failed to read bundle mediaType: %v" , err ), ext .GetGeneration ())
175
+ }
176
+ setProgressingStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("failed to read bundle mediaType: %v" , err ), ext .GetGeneration ())
169
177
return ctrl.Result {}, err
170
178
}
171
179
172
180
// TODO: this needs to include the registryV1 bundle option. As of this PR, this only supports direct
173
181
// installation of a set of manifests.
174
182
if mediaType != catalogmetadata .MediaTypePlain {
175
- // Set the TypeInstalled condition to Unknown to indicate that the resolution
176
- // hasn't been attempted yet, due to the spec being invalid.
177
- ext .Status .InstalledBundle = nil
178
- setInstalledStatusConditionUnknown (& ext .Status .Conditions , fmt .Sprintf ("bundle type %s not supported currently" , mediaType ), ext .GetGeneration ())
179
- setDeprecationStatusesUnknown (& ext .Status .Conditions , "deprecation checks have not been attempted as installation has failed" , ext .GetGeneration ())
183
+ if c := apimeta .FindStatusCondition (ext .Status .Conditions , ocv1alpha1 .TypeInstalled ); c == nil {
184
+ // Set the TypeInstalled condition to Failed to indicate that the resolution
185
+ // hasn't been attempted yet, due to the spec being invalid.
186
+ ext .Status .InstalledBundle = nil
187
+ setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("bundle type %s not supported currently" , mediaType ), ext .GetGeneration ())
188
+ }
189
+ setProgressingStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("bundle type %s not supported currently" , mediaType ), ext .GetGeneration ())
180
190
return ctrl.Result {}, nil
181
191
}
182
192
183
193
app , err := r .GenerateExpectedApp (* ext , bundle )
184
194
if err != nil {
185
- setInstalledStatusConditionUnknown (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
186
- setDeprecationStatusesUnknown (& ext .Status .Conditions , "deprecation checks have not been attempted as installation has failed" , ext .GetGeneration ())
195
+ if c := apimeta .FindStatusCondition (ext .Status .Conditions , ocv1alpha1 .TypeInstalled ); c == nil {
196
+ ext .Status .InstalledBundle = nil
197
+ setInstalledStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
198
+ }
199
+ setProgressingStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
187
200
return ctrl.Result {}, err
188
201
}
189
202
190
203
if err := r .ensureApp (ctx , app ); err != nil {
191
204
// originally Reason: ocv1alpha1.ReasonInstallationFailed
192
205
ext .Status .InstalledBundle = nil
193
206
setInstalledStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
207
+ setProgressingStatusConditionProgressing (& ext .Status .Conditions , "installation failed" , ext .GetGeneration ())
194
208
return ctrl.Result {}, err
195
209
}
196
210
@@ -199,14 +213,16 @@ func (r *ExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alpha1.Ext
199
213
if err := runtime .DefaultUnstructuredConverter .FromUnstructured (app .UnstructuredContent (), existingTypedApp ); err != nil {
200
214
// originally Reason: ocv1alpha1.ReasonInstallationStatusUnknown
201
215
ext .Status .InstalledBundle = nil
202
- setInstalledStatusConditionUnknown (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
203
- setDeprecationStatusesUnknown (& ext .Status .Conditions , "deprecation checks have not been attempted as installation has failed" , ext .GetGeneration ())
216
+ setInstalledStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
217
+ setProgressingStatusConditionProgressing (& ext .Status .Conditions , "installation failed" , ext .GetGeneration ())
204
218
return ctrl.Result {}, err
205
219
}
206
220
207
- version , _ := bundle .Version ()
208
- MapAppStatusToCondition (existingTypedApp , ext , & ocv1alpha1.BundleMetadata {Name : bundle .Name , Version : fmt .Sprintf ("%v" , version )})
209
- SetDeprecationStatusInExtension (ext , bundle )
221
+ ext .Status .InstalledBundle = bundleMetadataFor (bundle )
222
+ setInstalledStatusConditionSuccess (& ext .Status .Conditions , fmt .Sprintf ("successfully installed %v" , ext .Status .InstalledBundle ), ext .GetGeneration ())
223
+
224
+ // TODO: add conditions to determine extension health
225
+ mapAppStatusToCondition (existingTypedApp , ext )
210
226
211
227
return ctrl.Result {}, nil
212
228
}
@@ -230,63 +246,36 @@ func (r *ExtensionReconciler) SetupWithManager(mgr ctrl.Manager) error {
230
246
}
231
247
232
248
// mapAppStatusToCondition maps the reconciling/deleting App conditions to the installed/deleting conditions on the Extension.
233
- func MapAppStatusToCondition (existingApp * kappctrlv1alpha1.App , ext * ocv1alpha1.Extension , bundle * ocv1alpha1.BundleMetadata ) {
234
- if ext == nil {
235
- return
236
- }
237
- message := "install status unknown"
238
- ext .Status .InstalledBundle = nil
239
-
240
- if existingApp == nil {
241
- setInstalledStatusConditionUnknown (& ext .Status .Conditions , message , ext .Generation )
249
+ func mapAppStatusToCondition (existingApp * kappctrlv1alpha1.App , ext * ocv1alpha1.Extension ) {
250
+ // Note: App.Status.Inspect errors are never surfaced to App conditions, so are currently ignored when determining App status.
251
+ if ext == nil || existingApp == nil {
242
252
return
243
253
}
244
- message = existingApp .Status .FriendlyDescription
245
- if strings .Contains (message , "Error (see .status.usefulErrorMessage for details)" ) || len ( message ) == 0 {
254
+ message : = existingApp .Status .FriendlyDescription
255
+ if len ( message ) == 0 || strings .Contains (message , "Error (see .status.usefulErrorMessage for details)" ) {
246
256
message = existingApp .Status .UsefulErrorMessage
247
257
}
248
258
249
- orderedAppStatuses := []kappctrlv1alpha1.ConditionType {
250
- kappctrlv1alpha1 .DeleteFailed ,
251
- kappctrlv1alpha1 .Deleting ,
252
- kappctrlv1alpha1 .ReconcileSucceeded ,
253
- kappctrlv1alpha1 .ReconcileFailed ,
254
- kappctrlv1alpha1 .Reconciling ,
255
- }
256
259
appStatusMapFn := map [kappctrlv1alpha1.ConditionType ]func (* []metav1.Condition , string , int64 ){
257
- kappctrlv1alpha1 .DeleteFailed : setInstalledStatusConditionDeleteFailed ,
258
- kappctrlv1alpha1 .Deleting : setInstalledStatusConditionDeleting ,
259
- kappctrlv1alpha1 .ReconcileSucceeded : setInstalledStatusConditionSuccess ,
260
- kappctrlv1alpha1 .ReconcileFailed : setInstalledStatusConditionFailed ,
261
- kappctrlv1alpha1 .Reconciling : setInstalledStatusConditionUnknown ,
260
+ kappctrlv1alpha1 .Deleting : setProgressingStatusConditionProgressing ,
261
+ kappctrlv1alpha1 .Reconciling : setProgressingStatusConditionProgressing ,
262
+ kappctrlv1alpha1 .DeleteFailed : setProgressingStatusConditionFailed ,
263
+ kappctrlv1alpha1 .ReconcileFailed : setProgressingStatusConditionFailed ,
264
+ kappctrlv1alpha1 .ReconcileSucceeded : setProgressingStatusConditionSuccess ,
262
265
}
263
- for _ , cond := range orderedAppStatuses {
266
+ for cond := range appStatusMapFn {
264
267
if c := findStatusCondition (existingApp .Status .GenericStatus .Conditions , cond ); c != nil && c .Status == corev1 .ConditionTrue {
265
268
if len (message ) == 0 {
266
269
message = c .Message
267
270
}
268
- if c .Type == kappctrlv1alpha1 .ReconcileSucceeded {
269
- ext .Status .InstalledBundle = bundle
270
- }
271
- appStatusMapFn [cond ](& ext .Status .Conditions , message , ext .Generation )
271
+ appStatusMapFn [cond ](& ext .Status .Conditions , fmt .Sprintf ("App %s: %s" , c .Type , message ), ext .Generation )
272
272
return
273
273
}
274
274
}
275
275
if len (message ) == 0 {
276
- message = "install status unknown"
277
- }
278
- setInstalledStatusConditionUnknown (& ext .Status .Conditions , message , ext .Generation )
279
- }
280
-
281
- // findStatusCondition finds the conditionType in conditions.
282
- // TODO: suggest using upstream conditions to Carvel.
283
- func findStatusCondition (conditions []kappctrlv1alpha1.Condition , conditionType kappctrlv1alpha1.ConditionType ) * kappctrlv1alpha1.Condition {
284
- for i := range conditions {
285
- if conditions [i ].Type == conditionType {
286
- return & conditions [i ]
287
- }
276
+ message = "waiting for app"
288
277
}
289
- return nil
278
+ setProgressingStatusConditionProgressing ( & ext . Status . Conditions , message , ext . Generation )
290
279
}
291
280
292
281
// setDeprecationStatus will set the appropriate deprecation statuses for a Extension
@@ -371,6 +360,17 @@ func SetDeprecationStatusInExtension(ext *ocv1alpha1.Extension, bundle *catalogm
371
360
}
372
361
}
373
362
363
+ // findStatusCondition finds the conditionType in conditions.
364
+ // TODO: suggest using upstream conditions to Carvel.
365
+ func findStatusCondition (conditions []kappctrlv1alpha1.Condition , conditionType kappctrlv1alpha1.ConditionType ) * kappctrlv1alpha1.Condition {
366
+ for i := range conditions {
367
+ if conditions [i ].Type == conditionType {
368
+ return & conditions [i ]
369
+ }
370
+ }
371
+ return nil
372
+ }
373
+
374
374
func (r * ExtensionReconciler ) ensureApp (ctx context.Context , desiredApp * unstructured.Unstructured ) error {
375
375
existingApp , err := r .existingAppUnstructured (ctx , desiredApp .GetName (), desiredApp .GetNamespace ())
376
376
if client .IgnoreNotFound (err ) != nil {
0 commit comments