Skip to content

Commit 8d06a34

Browse files
committed
Implement Installed condition
Signed-off-by: Joaquim Moreno Prusi <[email protected]>
1 parent 8779806 commit 8d06a34

File tree

3 files changed

+229
-1
lines changed

3 files changed

+229
-1
lines changed

controllers/operator_controller.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ func checkForUnexpectedFieldChange(a, b operatorsv1alpha1.Operator) bool {
106106
func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha1.Operator) (ctrl.Result, error) {
107107
// validate spec
108108
if err := validators.ValidateOperatorSpec(op); err != nil {
109+
// Set the TypeInstalled condition to Unknown to indicate that the resolution
110+
// hasn't been attempted yet, due to the spec being invalid.
111+
op.Status.InstalledBundleSource = ""
112+
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
113+
Type: operatorsv1alpha1.TypeInstalled,
114+
Status: metav1.ConditionUnknown,
115+
Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown,
116+
Message: "installation has not been attempted as spec is invalid",
117+
ObservedGeneration: op.GetGeneration(),
118+
})
109119
// Set the TypeResolved condition to Unknown to indicate that the resolution
110120
// hasn't been attempted yet, due to the spec being invalid.
111121
op.Status.ResolvedBundleResource = ""
@@ -121,6 +131,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
121131
// run resolution
122132
solution, err := r.Resolver.Resolve(ctx)
123133
if err != nil {
134+
op.Status.InstalledBundleSource = ""
135+
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
136+
Type: operatorsv1alpha1.TypeInstalled,
137+
Status: metav1.ConditionUnknown,
138+
Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown,
139+
Message: "installation has not been attempted as resolution failed",
140+
ObservedGeneration: op.GetGeneration(),
141+
})
124142
op.Status.ResolvedBundleResource = ""
125143
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
126144
Type: operatorsv1alpha1.TypeResolved,
@@ -136,6 +154,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
136154
// Operator's desired package name.
137155
bundleEntity, err := r.getBundleEntityFromSolution(solution, op.Spec.PackageName)
138156
if err != nil {
157+
op.Status.InstalledBundleSource = ""
158+
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
159+
Type: operatorsv1alpha1.TypeInstalled,
160+
Status: metav1.ConditionUnknown,
161+
Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown,
162+
Message: "installation has not been attempted as resolution failed",
163+
ObservedGeneration: op.GetGeneration(),
164+
})
139165
op.Status.ResolvedBundleResource = ""
140166
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
141167
Type: operatorsv1alpha1.TypeResolved,
@@ -150,6 +176,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
150176
// Get the bundle image reference for the bundle
151177
bundleImage, err := bundleEntity.BundlePath()
152178
if err != nil {
179+
op.Status.InstalledBundleSource = ""
180+
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
181+
Type: operatorsv1alpha1.TypeInstalled,
182+
Status: metav1.ConditionUnknown,
183+
Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown,
184+
Message: "installation has not been attempted as resolution failed",
185+
ObservedGeneration: op.GetGeneration(),
186+
})
153187
op.Status.ResolvedBundleResource = ""
154188
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
155189
Type: operatorsv1alpha1.TypeResolved,
@@ -176,20 +210,93 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
176210
dep := r.generateExpectedBundleDeployment(*op, bundleImage)
177211
if err := r.ensureBundleDeployment(ctx, dep); err != nil {
178212
// originally Reason: operatorsv1alpha1.ReasonInstallationFailed
213+
op.Status.InstalledBundleSource = ""
214+
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
215+
Type: operatorsv1alpha1.TypeInstalled,
216+
Status: metav1.ConditionFalse,
217+
Reason: operatorsv1alpha1.ReasonInstallationFailed,
218+
Message: err.Error(),
219+
ObservedGeneration: op.GetGeneration(),
220+
})
179221
return ctrl.Result{}, err
180222
}
181223

182224
// convert existing unstructured object into bundleDeployment for easier mapping of status.
183225
existingTypedBundleDeployment := &rukpakv1alpha1.BundleDeployment{}
184226
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(dep.UnstructuredContent(), existingTypedBundleDeployment); err != nil {
185227
// originally Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown
228+
op.Status.InstalledBundleSource = ""
229+
apimeta.SetStatusCondition(&op.Status.Conditions, metav1.Condition{
230+
Type: operatorsv1alpha1.TypeInstalled,
231+
Status: metav1.ConditionUnknown,
232+
Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown,
233+
Message: err.Error(),
234+
ObservedGeneration: op.GetGeneration(),
235+
})
186236
return ctrl.Result{}, err
187237
}
188238

239+
// Let's set the proper Installed condition and installedBundleSource field based on the
240+
// existing BundleDeployment object status.
241+
installedCond, installedBundleSource := mapBDStatusToInstalledCondition(existingTypedBundleDeployment, op)
242+
apimeta.SetStatusCondition(&op.Status.Conditions, installedCond)
243+
op.Status.InstalledBundleSource = installedBundleSource
244+
189245
// set the status of the operator based on the respective bundle deployment status conditions.
190246
return ctrl.Result{}, nil
191247
}
192248

249+
func mapBDStatusToInstalledCondition(existingTypedBundleDeployment *rukpakv1alpha1.BundleDeployment, op *operatorsv1alpha1.Operator) (metav1.Condition, string) {
250+
bundleDeploymentReady := apimeta.FindStatusCondition(existingTypedBundleDeployment.Status.Conditions, rukpakv1alpha1.TypeInstalled)
251+
if bundleDeploymentReady == nil {
252+
return metav1.Condition{
253+
Type: operatorsv1alpha1.TypeInstalled,
254+
Status: metav1.ConditionUnknown,
255+
Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown,
256+
Message: "bundledeployment status is unknown",
257+
ObservedGeneration: op.GetGeneration(),
258+
}, ""
259+
}
260+
261+
if bundleDeploymentReady.Status != metav1.ConditionTrue {
262+
return metav1.Condition{
263+
Type: operatorsv1alpha1.TypeInstalled,
264+
Status: metav1.ConditionFalse,
265+
Reason: operatorsv1alpha1.ReasonInstallationFailed,
266+
Message: fmt.Sprintf("bundledeployment not ready: %s", bundleDeploymentReady.Message),
267+
ObservedGeneration: op.GetGeneration(),
268+
}, ""
269+
}
270+
271+
bundleDeploymentSource := existingTypedBundleDeployment.Spec.Template.Spec.Source
272+
switch bundleDeploymentSource.Type {
273+
case rukpakv1alpha1.SourceTypeImage:
274+
return metav1.Condition{
275+
Type: operatorsv1alpha1.TypeInstalled,
276+
Status: metav1.ConditionTrue,
277+
Reason: operatorsv1alpha1.ReasonSuccess,
278+
Message: fmt.Sprintf("installed from %q", bundleDeploymentSource.Image.Ref),
279+
ObservedGeneration: op.GetGeneration(),
280+
}, bundleDeploymentSource.Image.Ref
281+
case rukpakv1alpha1.SourceTypeGit:
282+
return metav1.Condition{
283+
Type: operatorsv1alpha1.TypeInstalled,
284+
Status: metav1.ConditionTrue,
285+
Reason: operatorsv1alpha1.ReasonSuccess,
286+
Message: fmt.Sprintf("installed from %q", bundleDeploymentSource.Git.Repository+"@"+bundleDeploymentSource.Git.Ref.Commit),
287+
ObservedGeneration: op.GetGeneration(),
288+
}, bundleDeploymentSource.Git.Repository + "@" + bundleDeploymentSource.Git.Ref.Commit
289+
default:
290+
return metav1.Condition{
291+
Type: operatorsv1alpha1.TypeInstalled,
292+
Status: metav1.ConditionUnknown,
293+
Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown,
294+
Message: fmt.Sprintf("unknown bundledeployment source type %q", bundleDeploymentSource.Type),
295+
ObservedGeneration: op.GetGeneration(),
296+
}, ""
297+
}
298+
}
299+
193300
func (r *OperatorReconciler) getBundleEntityFromSolution(solution *solver.Solution, packageName string) (*entity.BundleEntity, error) {
194301
for _, variable := range solution.SelectedVariables() {
195302
switch v := variable.(type) {

0 commit comments

Comments
 (0)