Skip to content

Commit 05375cb

Browse files
perdasilvaPer Goncalves da Silva
andauthored
✨ Set Availability condition to Unknown on archived revisions (#2261)
* Add AVAILABLE print column to ClusterExtensionRevision Signed-off-by: Per Goncalves da Silva <[email protected]> * Update resources for print column Signed-off-by: Per Goncalves da Silva <[email protected]> * Set Available condition to Unknown on archived revisions Signed-off-by: Per Goncalves da Silva <[email protected]> * Remove condition setting on finalizer removal Signed-off-by: Per Goncalves da Silva <[email protected]> --------- Signed-off-by: Per Goncalves da Silva <[email protected]> Co-authored-by: Per Goncalves da Silva <[email protected]>
1 parent 94f2e67 commit 05375cb

File tree

6 files changed

+124
-50
lines changed

6 files changed

+124
-50
lines changed

api/v1/clusterextensionrevision_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const (
3939
ClusterExtensionRevisionReasonProbeFailure = "ProbeFailure"
4040
ClusterExtensionRevisionReasonIncomplete = "Incomplete"
4141
ClusterExtensionRevisionReasonProgressing = "Progressing"
42+
ClusterExtensionRevisionReasonArchived = "Archived"
4243
)
4344

4445
// ClusterExtensionRevisionSpec defines the desired state of ClusterExtensionRevision.
@@ -148,6 +149,8 @@ type ClusterExtensionRevisionStatus struct {
148149
// +kubebuilder:subresource:status
149150

150151
// ClusterExtensionRevision is the Schema for the clusterextensionrevisions API
152+
// +kubebuilder:printcolumn:name="Available",type=string,JSONPath=`.status.conditions[?(@.type=='Available')].status`
153+
// +kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp`
151154
type ClusterExtensionRevision struct {
152155
metav1.TypeMeta `json:",inline"`
153156
metav1.ObjectMeta `json:"metadata,omitempty"`

helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensionrevisions.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ spec:
1515
singular: clusterextensionrevision
1616
scope: Cluster
1717
versions:
18-
- name: v1
18+
- additionalPrinterColumns:
19+
- jsonPath: .status.conditions[?(@.type=='Available')].status
20+
name: Available
21+
type: string
22+
- jsonPath: .metadata.creationTimestamp
23+
name: Age
24+
type: date
25+
name: v1
1926
schema:
2027
openAPIV3Schema:
2128
description: ClusterExtensionRevision is the Schema for the clusterextensionrevisions

internal/operator-controller/controllers/clusterextensionrevision_controller.go

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -118,52 +118,8 @@ func (c *ClusterExtensionRevisionReconciler) reconcile(ctx context.Context, rev
118118

119119
revision, opts, previous := toBoxcutterRevision(rev)
120120

121-
if !rev.DeletionTimestamp.IsZero() ||
122-
rev.Spec.LifecycleState == ocv1.ClusterExtensionRevisionLifecycleStateArchived {
123-
//
124-
// Teardown
125-
//
126-
tres, err := c.RevisionEngine.Teardown(ctx, *revision)
127-
if err != nil {
128-
meta.SetStatusCondition(&rev.Status.Conditions, metav1.Condition{
129-
Type: ocv1.ClusterExtensionRevisionTypeAvailable,
130-
Status: metav1.ConditionFalse,
131-
Reason: ocv1.ClusterExtensionRevisionReasonReconcileFailure,
132-
Message: err.Error(),
133-
ObservedGeneration: rev.Generation,
134-
})
135-
return ctrl.Result{}, fmt.Errorf("revision teardown: %v", err)
136-
}
137-
138-
l.Info("teardown report", "report", tres.String())
139-
if !tres.IsComplete() {
140-
// TODO: If it is not complete, it seems like it would be good to update
141-
// the status in some way to tell the user that the teardown is still
142-
// in progress.
143-
return ctrl.Result{}, nil
144-
}
145-
146-
if err := c.TrackingCache.Free(ctx, rev); err != nil {
147-
meta.SetStatusCondition(&rev.Status.Conditions, metav1.Condition{
148-
Type: ocv1.ClusterExtensionRevisionTypeAvailable,
149-
Status: metav1.ConditionFalse,
150-
Reason: ocv1.ClusterExtensionRevisionReasonReconcileFailure,
151-
Message: err.Error(),
152-
ObservedGeneration: rev.Generation,
153-
})
154-
return ctrl.Result{}, fmt.Errorf("error stopping informers: %v", err)
155-
}
156-
if err := c.removeFinalizer(ctx, rev, clusterExtensionRevisionTeardownFinalizer); err != nil {
157-
meta.SetStatusCondition(&rev.Status.Conditions, metav1.Condition{
158-
Type: "Available",
159-
Status: metav1.ConditionFalse,
160-
Reason: "ReconcileFailure",
161-
Message: err.Error(),
162-
ObservedGeneration: rev.Generation,
163-
})
164-
return ctrl.Result{}, fmt.Errorf("error removing teardown finalizer: %v", err)
165-
}
166-
return ctrl.Result{}, nil
121+
if !rev.DeletionTimestamp.IsZero() || rev.Spec.LifecycleState == ocv1.ClusterExtensionRevisionLifecycleStateArchived {
122+
return c.teardown(ctx, rev, revision)
167123
}
168124

169125
//
@@ -339,6 +295,59 @@ func (c *ClusterExtensionRevisionReconciler) reconcile(ctx context.Context, rev
339295
return ctrl.Result{}, nil
340296
}
341297

298+
func (c *ClusterExtensionRevisionReconciler) teardown(ctx context.Context, rev *ocv1.ClusterExtensionRevision, revision *boxcutter.Revision) (ctrl.Result, error) {
299+
l := log.FromContext(ctx)
300+
301+
tres, err := c.RevisionEngine.Teardown(ctx, *revision)
302+
if err != nil {
303+
meta.SetStatusCondition(&rev.Status.Conditions, metav1.Condition{
304+
Type: ocv1.ClusterExtensionRevisionTypeAvailable,
305+
Status: metav1.ConditionFalse,
306+
Reason: ocv1.ClusterExtensionRevisionReasonReconcileFailure,
307+
Message: err.Error(),
308+
ObservedGeneration: rev.Generation,
309+
})
310+
return ctrl.Result{}, fmt.Errorf("revision teardown: %v", err)
311+
}
312+
313+
l.Info("teardown report", "report", tres.String())
314+
if !tres.IsComplete() {
315+
// TODO: If it is not complete, it seems like it would be good to update
316+
// the status in some way to tell the user that the teardown is still
317+
// in progress.
318+
return ctrl.Result{}, nil
319+
}
320+
321+
if err := c.TrackingCache.Free(ctx, rev); err != nil {
322+
meta.SetStatusCondition(&rev.Status.Conditions, metav1.Condition{
323+
Type: ocv1.ClusterExtensionRevisionTypeAvailable,
324+
Status: metav1.ConditionFalse,
325+
Reason: ocv1.ClusterExtensionRevisionReasonReconcileFailure,
326+
Message: err.Error(),
327+
ObservedGeneration: rev.Generation,
328+
})
329+
return ctrl.Result{}, fmt.Errorf("error stopping informers: %v", err)
330+
}
331+
332+
// Ensure Available condition is set to Unknown before removing the finalizer when archiving
333+
if rev.Spec.LifecycleState == ocv1.ClusterExtensionRevisionLifecycleStateArchived &&
334+
!meta.IsStatusConditionPresentAndEqual(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable, metav1.ConditionUnknown) {
335+
meta.SetStatusCondition(&rev.Status.Conditions, metav1.Condition{
336+
Type: ocv1.ClusterExtensionRevisionTypeAvailable,
337+
Status: metav1.ConditionUnknown,
338+
Reason: ocv1.ClusterExtensionRevisionReasonArchived,
339+
Message: "revision is archived",
340+
ObservedGeneration: rev.Generation,
341+
})
342+
return ctrl.Result{}, nil
343+
}
344+
345+
if err := c.removeFinalizer(ctx, rev, clusterExtensionRevisionTeardownFinalizer); err != nil {
346+
return ctrl.Result{}, fmt.Errorf("error removing teardown finalizer: %v", err)
347+
}
348+
return ctrl.Result{}, nil
349+
}
350+
342351
type Sourcerer interface {
343352
Source(handler handler.EventHandler, predicates ...predicate.Predicate) source.Source
344353
}

internal/operator-controller/controllers/clusterextensionrevision_controller_test.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,40 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_Deletion(t *testing.T) {
544544
require.NotContains(t, "olm.operatorframework.io/teardown", rev.Finalizers)
545545
},
546546
},
547+
{
548+
name: "set Available condition to Unknown with reason Archived when archiving revision",
549+
revisionResult: mockRevisionResult{},
550+
existingObjs: func() []client.Object {
551+
ext := newTestClusterExtension()
552+
rev1 := newTestClusterExtensionRevision(clusterExtensionRevisionName)
553+
rev1.Finalizers = []string{
554+
"olm.operatorframework.io/teardown",
555+
}
556+
rev1.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
557+
require.NoError(t, controllerutil.SetControllerReference(ext, rev1, testScheme))
558+
return []client.Object{rev1, ext}
559+
},
560+
revisionEngineTeardownFn: func(t *testing.T) func(ctx context.Context, rev machinerytypes.Revision, opts ...machinerytypes.RevisionTeardownOption) (machinery.RevisionTeardownResult, error) {
561+
return func(ctx context.Context, rev machinerytypes.Revision, opts ...machinerytypes.RevisionTeardownOption) (machinery.RevisionTeardownResult, error) {
562+
return &mockRevisionTeardownResult{
563+
isComplete: true,
564+
}, nil
565+
}
566+
},
567+
validate: func(t *testing.T, c client.Client) {
568+
rev := &ocv1.ClusterExtensionRevision{}
569+
err := c.Get(t.Context(), client.ObjectKey{
570+
Name: clusterExtensionRevisionName,
571+
}, rev)
572+
require.NoError(t, err)
573+
cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
574+
require.NotNil(t, cond)
575+
require.Equal(t, metav1.ConditionUnknown, cond.Status)
576+
require.Equal(t, ocv1.ClusterExtensionRevisionReasonArchived, cond.Reason)
577+
require.Equal(t, "revision is archived", cond.Message)
578+
require.Equal(t, int64(1), cond.ObservedGeneration)
579+
},
580+
},
547581
{
548582
name: "revision is torn down when in archived state and finalizer is removed",
549583
revisionResult: mockRevisionResult{},
@@ -554,6 +588,13 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_Deletion(t *testing.T) {
554588
"olm.operatorframework.io/teardown",
555589
}
556590
rev1.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
591+
meta.SetStatusCondition(&rev1.Status.Conditions, metav1.Condition{
592+
Type: ocv1.ClusterExtensionRevisionTypeAvailable,
593+
Status: metav1.ConditionUnknown,
594+
Reason: ocv1.ClusterExtensionRevisionReasonArchived,
595+
Message: "revision is archived",
596+
ObservedGeneration: rev1.Generation,
597+
})
557598
require.NoError(t, controllerutil.SetControllerReference(ext, rev1, testScheme))
558599
return []client.Object{rev1, ext}
559600
},
@@ -570,7 +611,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_Deletion(t *testing.T) {
570611
Name: clusterExtensionRevisionName,
571612
}, rev)
572613
require.NoError(t, err)
573-
require.NotContains(t, "olm.operatorframework.io/teardown", rev.Finalizers)
614+
require.NotContains(t, rev.Finalizers, "olm.operatorframework.io/teardown")
574615
},
575616
},
576617
{

manifests/experimental-e2e.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,14 @@ spec:
606606
singular: clusterextensionrevision
607607
scope: Cluster
608608
versions:
609-
- name: v1
609+
- additionalPrinterColumns:
610+
- jsonPath: .status.conditions[?(@.type=='Available')].status
611+
name: Available
612+
type: string
613+
- jsonPath: .metadata.creationTimestamp
614+
name: Age
615+
type: date
616+
name: v1
610617
schema:
611618
openAPIV3Schema:
612619
description: ClusterExtensionRevision is the Schema for the clusterextensionrevisions

manifests/experimental.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,14 @@ spec:
571571
singular: clusterextensionrevision
572572
scope: Cluster
573573
versions:
574-
- name: v1
574+
- additionalPrinterColumns:
575+
- jsonPath: .status.conditions[?(@.type=='Available')].status
576+
name: Available
577+
type: string
578+
- jsonPath: .metadata.creationTimestamp
579+
name: Age
580+
type: date
581+
name: v1
575582
schema:
576583
openAPIV3Schema:
577584
description: ClusterExtensionRevision is the Schema for the clusterextensionrevisions

0 commit comments

Comments
 (0)