Skip to content

Commit 74f5a36

Browse files
cleanup: refactor cleanup to let olm delete resources (#4233)
Refactor cleanup to delete crds and csv instead of individually deleting the resources referenced in install plan. OLM applies an ownerref on every namespaced resource to the CSV, and an owner label on cluster scoped resources. OLM and kube garbage collector will delete the resources referenced in csv.
1 parent d514a1e commit 74f5a36

File tree

1 file changed

+40
-52
lines changed

1 file changed

+40
-52
lines changed

internal/olm/operator/uninstall.go

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222

2323
v1 "github.com/operator-framework/api/pkg/operators/v1"
2424
"github.com/operator-framework/api/pkg/operators/v1alpha1"
25-
"github.com/operator-framework/operator-registry/pkg/lib/bundle"
2625
apierrors "k8s.io/apimachinery/pkg/api/errors"
2726
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2827
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -31,7 +30,11 @@ import (
3130
"k8s.io/kubectl/pkg/util/slice"
3231
"sigs.k8s.io/controller-runtime/pkg/client"
3332
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
34-
"sigs.k8s.io/yaml"
33+
)
34+
35+
const (
36+
csvKind = "ClusterServiceVersion"
37+
crdKind = "CustomResourceDefinition"
3538
)
3639

3740
type Uninstall struct {
@@ -91,22 +94,13 @@ func (u *Uninstall) Run(ctx context.Context) error {
9194
return fmt.Errorf("get catalog source: %v", err)
9295
}
9396

94-
// Since the install plan is owned by the subscription, we need to
95-
// read all of the resource references from the install plan before
96-
// deleting the subscription.
97-
var crds, csvs, others []controllerutil.Object
98-
if sub.Status.InstallPlanRef != nil {
99-
ipKey := types.NamespacedName{
100-
Namespace: sub.Status.InstallPlanRef.Namespace,
101-
Name: sub.Status.InstallPlanRef.Name,
102-
}
103-
var err error
104-
crds, csvs, others, err = u.getInstallPlanResources(ctx, ipKey)
105-
if err != nil {
106-
return fmt.Errorf("get install plan resources: %v", err)
107-
}
97+
csv, err := u.getInstalledCSV(ctx, sub)
98+
if err != nil {
99+
return fmt.Errorf("get installed CSV %q: %v", sub.Status.InstalledCSV, err)
108100
}
109101

102+
crds := getCRDs(csv)
103+
110104
// Delete the subscription first, so that no further installs or upgrades
111105
// of the operator occur while we're cleaning up.
112106
if err := u.deleteObjects(ctx, false, sub); err != nil {
@@ -121,11 +115,13 @@ func (u *Uninstall) Run(ctx context.Context) error {
121115
}
122116
}
123117

124-
// Delete CSVs and all other objects created by the install plan.
125-
objects := append(csvs, others...)
126-
if err := u.deleteObjects(ctx, true, objects...); err != nil {
118+
// OLM puts an ownerref on every namespaced resource to the CSV,
119+
// and an owner label on every cluster scoped resource. When CSV is deleted
120+
// kube and olm gc will remove all the referenced resources.
121+
if err := u.deleteObjects(ctx, true, csv); err != nil {
127122
return err
128123
}
124+
129125
} else {
130126
catsrc.SetNamespace(u.config.Namespace)
131127
catsrc.SetName(CatalogNameForPackage(u.Package))
@@ -194,43 +190,35 @@ func (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs
194190
return nil
195191
}
196192

197-
func (u *Uninstall) getInstallPlanResources(ctx context.Context, installPlanKey types.NamespacedName) (crds, csvs, others []controllerutil.Object, err error) {
198-
installPlan := &v1alpha1.InstallPlan{}
199-
if err := u.config.Client.Get(ctx, installPlanKey, installPlan); err != nil {
200-
return nil, nil, nil, fmt.Errorf("get install plan: %v", err)
193+
// getInstalledCSV looks up the installed CSV name from the provided subscription and fetches it.
194+
func (u *Uninstall) getInstalledCSV(ctx context.Context, subscription *v1alpha1.Subscription) (*v1alpha1.ClusterServiceVersion, error) {
195+
key := types.NamespacedName{
196+
Name: subscription.Status.InstalledCSV,
197+
Namespace: subscription.GetNamespace(),
201198
}
202199

203-
for _, step := range installPlan.Status.Plan {
204-
lowerKind := strings.ToLower(step.Resource.Kind)
205-
obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
206-
if err := yaml.Unmarshal([]byte(step.Resource.Manifest), &obj.Object); err != nil {
207-
return nil, nil, nil, fmt.Errorf("parse %s manifest %q: %v", lowerKind, step.Resource.Name, err)
208-
}
209-
obj.SetGroupVersionKind(schema.GroupVersionKind{
210-
Group: step.Resource.Group,
211-
Version: step.Resource.Version,
212-
Kind: step.Resource.Kind,
213-
})
214-
215-
// TODO(joelanford): This seems necessary for namespaced resources
216-
// See: https://github.com/operator-framework/operator-lifecycle-manager/blob/c9405d035bc50d9aa290220cb8d75b0402e72707/pkg/controller/registry/resolver/rbac.go#L133
217-
if supported, namespaced := bundle.IsSupported(step.Resource.Kind); supported && bool(namespaced) {
218-
obj.SetNamespace(installPlanKey.Namespace)
219-
}
200+
installedCSV := &v1alpha1.ClusterServiceVersion{}
201+
if err := u.config.Client.Get(ctx, key, installedCSV); err != nil {
202+
return nil, err
203+
}
220204

221-
switch step.Resource.Kind {
222-
case "CustomResourceDefinition":
205+
installedCSV.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(csvKind))
206+
return installedCSV, nil
207+
}
208+
209+
// getCRDs returns the list of CRDs required by a CSV.
210+
func getCRDs(csv *v1alpha1.ClusterServiceVersion) (crds []controllerutil.Object) {
211+
for _, resource := range csv.Status.RequirementStatus {
212+
if resource.Kind == crdKind {
213+
obj := &unstructured.Unstructured{}
214+
obj.SetGroupVersionKind(schema.GroupVersionKind{
215+
Group: resource.Group,
216+
Version: resource.Version,
217+
Kind: resource.Kind,
218+
})
219+
obj.SetName(resource.Name)
223220
crds = append(crds, obj)
224-
case "ClusterServiceVersion":
225-
csvs = append(csvs, obj)
226-
default:
227-
// Skip non-CRD/non-CSV resources in the install plan that were not created by the install plan.
228-
// This means we avoid deleting things like the default service account.
229-
if step.Status != v1alpha1.StepStatusCreated {
230-
continue
231-
}
232-
others = append(others, obj)
233221
}
234222
}
235-
return crds, csvs, others, nil
223+
return
236224
}

0 commit comments

Comments
 (0)