Skip to content

Commit

Permalink
gc
Browse files Browse the repository at this point in the history
  • Loading branch information
lburgazzoli committed Feb 4, 2025
1 parent 2b2ba5b commit 128b55c
Showing 1 changed file with 52 additions and 70 deletions.
122 changes: 52 additions & 70 deletions pkg/services/gc/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ import (
"github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/client"
)

// Instance a global instance of the GC service.
//
// TODO: since the GC service is quite heavy, as it has to discover
//
// resources that can be subject to GC, we share single global
// instance, however as long term, we should find a better way
// to let consumer of the service to access it.
// resources that can be subject to GC, we share single global
// instance, however as long term, we should find a better way
// to let consumer of the service to access it.

// Instance a global instance of the GC service.
var Instance *GC

const (
Expand All @@ -39,14 +38,16 @@ const (

type options struct {
propagationPolicy ctrlCli.PropagationPolicy
unremovables []schema.GroupVersionKind
unremovables map[schema.GroupVersionKind]struct{}
}

type OptsFn func(*options)

func WithUnremovables(items ...schema.GroupVersionKind) OptsFn {
return func(o *options) {
o.unremovables = append(o.unremovables, items...)
for _, i := range items {
o.unremovables[i] = struct{}{}
}
}
}

Expand All @@ -62,7 +63,7 @@ func New(cli *client.Client, ns string, opts ...OptsFn) *GC {
ns: ns,
options: options{
propagationPolicy: ctrlCli.PropagationPolicy(metav1.DeletePropagationForeground),
unremovables: make([]schema.GroupVersionKind, 0),
unremovables: make(map[schema.GroupVersionKind]struct{}),
},

resources: Resources{
Expand Down Expand Up @@ -118,13 +119,34 @@ func WitTypeFilter(fn func(context.Context, schema.GroupVersionKind) (bool, erro
}
}

func (gc *GC) listResources(
ctx context.Context,
res Resource,
opts metav1.ListOptions,
) ([]unstructured.Unstructured, error) {
items, err := gc.client.Dynamic().Resource(res.GroupVersionResource()).Namespace("").List(ctx, opts)
if err != nil {
if k8serr.IsForbidden(err) || k8serr.IsMethodNotSupported(err) {
gc.log(ctx).V(3).Info(
"cannot list resource",
"reason", err.Error(),
"gvk", res.GroupVersionKind(),
)

return nil, nil
}

return nil, err
}

return items.Items, nil
}

func (gc *GC) Run(
ctx context.Context,
selector labels.Selector,
opts ...RunOptionsFn,
) (int, error) {
l := gc.log(ctx)

ro := runOptions{
typePredicate: func(_ context.Context, _ schema.GroupVersionKind) (bool, error) {
return true, nil
Expand All @@ -140,63 +162,33 @@ func (gc *GC) Run(

deleted := 0
resources := gc.resources.Get()

dc := gc.client.Dynamic()
lo := metav1.ListOptions{LabelSelector: selector.String()}

for r := range resources {
if slices.Contains(gc.options.unremovables, resources[r].GroupVersionKind()) {
continue
}

canBeDeleted, err := ro.typePredicate(ctx, resources[r].GroupVersionKind())
for _, res := range resources {
canBeDeleted, err := ro.typePredicate(ctx, res.GroupVersionKind())
if err != nil {
return 0, fmt.Errorf("cannot determine if resource %s can be deleted: %w", resources[r].String(), err)
return 0, fmt.Errorf("cannot determine if resource %s can be deleted: %w", res.String(), err)
}

if !canBeDeleted {
continue
}

items, err := dc.Resource(resources[r].GroupVersionResource()).Namespace("").List(ctx, lo)
items, err := gc.listResources(ctx, res, lo)
if err != nil {
if k8serr.IsForbidden(err) {
l.V(3).Info(
"cannot list resource",
"reason", err.Error(),
"gvk", resources[r].GroupVersionKind(),
)

continue
}

if k8serr.IsMethodNotSupported(err) {
l.V(3).Info(
"cannot list resource",
"reason", err.Error(),
"gvk", resources[r].GroupVersionKind(),
)

continue
}

if k8serr.IsNotFound(err) {
continue
}

return 0, fmt.Errorf("cannot list child resources %s: %w", resources[r].String(), err)
return 0, fmt.Errorf("cannot list child resources %s: %w", res.String(), err)
}

for i := range items.Items {
canBeDeleted, err = ro.objectPredicate(ctx, items.Items[i])
for i := range items {
canBeDeleted, err = ro.objectPredicate(ctx, items[i])
if err != nil {
return 0, err
}
if !canBeDeleted {
continue
}

if err := gc.delete(ctx, items.Items[i]); err != nil {
if err := gc.delete(ctx, items[i]); err != nil {
return 0, err
}

Expand Down Expand Up @@ -233,29 +225,19 @@ func (gc *GC) delete(
}

func (gc *GC) discoverResources() ([]*metav1.APIResourceList, error) {
// Notes:
// - We rely on the discovery API to retrieve all the resources GVK,
// that results in an unbounded set that can impact garbage collection
// latency when scaling up.
// - Swallow group discovery errors, e.g., Knative serving exposes
// an aggregated API for custom.metrics.k8s.io that requires special
// authentication scheme while discovering preferred resources.

namespacedItems, err := gc.client.Discovery().ServerPreferredNamespacedResources()
// We rely on the discovery API to retrieve all the resources GVK, that
// results in an unbounded set that can impact garbage collection latency
// when scaling up.
items, err := gc.client.Discovery().ServerPreferredResources()

// Swallow group discovery errors, e.g., Knative serving exposes an
// aggregated API for custom.metrics.k8s.io that requires special
// authentication scheme while discovering preferred resources.
if err != nil && !discovery.IsGroupDiscoveryFailedError(err) {
return nil, fmt.Errorf("failure retrieving supported namespaced resources: %w", err)
return nil, fmt.Errorf("failure retrieving supported resources: %w", err)
}

clusterItems, err := gc.client.Discovery().ServerPreferredResources()
if err != nil && !discovery.IsGroupDiscoveryFailedError(err) {
return nil, fmt.Errorf("failure retrieving supported cluster resources: %w", err)
}

res := make([]*metav1.APIResourceList, 0, len(namespacedItems)+len(clusterItems))
res = append(res, namespacedItems...)
res = append(res, clusterItems...)

return res, nil
return items, nil
}

func (gc *GC) computeDeletableTypes(
Expand Down Expand Up @@ -379,7 +361,7 @@ func (gc *GC) collectDeletableResources(
gvr.Scope = meta.RESTScopeRoot
}

if slices.Contains(gc.options.unremovables, gvr.GroupVersionKind()) {
if _, ok := gc.options.unremovables[gvr.GroupVersionKind()]; ok {
continue
}

Expand Down

0 comments on commit 128b55c

Please sign in to comment.