This is an automated email from the ASF dual-hosted git repository. nferraro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/master by this push: new dcb2b27 Fix #1364: only delete direct children of the integration during gc dcb2b27 is described below commit dcb2b27f3e2f16fa2b4825759db19072d8520c77 Author: Nicola Ferraro <ni.ferr...@gmail.com> AuthorDate: Tue Mar 24 15:15:37 2020 +0100 Fix #1364: only delete direct children of the integration during gc --- pkg/trait/gc.go | 66 +++++++++++++++++---------------------------------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/pkg/trait/gc.go b/pkg/trait/gc.go index 2c42cc9..5823b13 100644 --- a/pkg/trait/gc.go +++ b/pkg/trait/gc.go @@ -22,6 +22,7 @@ import ( "path/filepath" "regexp" "strconv" + "strings" "sync" "time" @@ -31,7 +32,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/selection" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/discovery" "k8s.io/client-go/discovery/cached/disk" "k8s.io/client-go/discovery/cached/memory" @@ -135,45 +135,15 @@ func (t *garbageCollectorTrait) garbageCollectResources(e *Environment) { Add(*integration). Add(*generation) - collectionGVKs, deletableGVKs, err := t.getDeletableTypes(e) + deletableGVKs, err := t.getDeletableTypes(e) if err != nil { t.L.ForIntegration(e.Integration).Errorf(err, "cannot discover GVK types") return } - t.deleteAllOf(collectionGVKs, e, selector) - // TODO: DeleteCollection is currently not supported for Service resources, so we have to keep - // client-side collection deletion around until it becomes supported. t.deleteEachOf(deletableGVKs, e, selector) } -func (t *garbageCollectorTrait) deleteAllOf(gvks map[schema.GroupVersionKind]struct{}, e *Environment, selector labels.Selector) { - for gvk := range gvks { - err := e.Client.DeleteAllOf(context.TODO(), - &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": gvk.GroupVersion().String(), - "kind": gvk.Kind, - "metadata": map[string]interface{}{ - "namespace": e.Integration.Namespace, - }, - }, - }, - // FIXME: The unstructured client doesn't take the namespace option into account - //controller.InNamespace(e.Integration.Namespace), - util.MatchingSelector{Selector: selector}, - client.PropagationPolicy(metav1.DeletePropagationBackground), - ) - if err != nil { - if !k8serrors.IsForbidden(err) { - t.L.ForIntegration(e.Integration).Errorf(err, "cannot delete child resources: %v", gvk) - } - } else { - t.L.ForIntegration(e.Integration).Debugf("child resources deleted: %v", gvk) - } - } -} - func (t *garbageCollectorTrait) deleteEachOf(gvks map[schema.GroupVersionKind]struct{}, e *Environment, selector labels.Selector) { for gvk := range gvks { resources := unstructured.UnstructuredList{ @@ -195,6 +165,9 @@ func (t *garbageCollectorTrait) deleteEachOf(gvks map[schema.GroupVersionKind]st for _, resource := range resources.Items { r := resource + if !t.canBeDeleted(e, r) { + continue + } err := t.Client.Delete(context.TODO(), &r, client.PropagationPolicy(metav1.DeletePropagationBackground)) if err != nil { // The resource may have already been deleted @@ -208,25 +181,34 @@ func (t *garbageCollectorTrait) deleteEachOf(gvks map[schema.GroupVersionKind]st } } -func (t *garbageCollectorTrait) getDeletableTypes(e *Environment) (map[schema.GroupVersionKind]struct{}, map[schema.GroupVersionKind]struct{}, error) { +func (t *garbageCollectorTrait) canBeDeleted(e *Environment, u unstructured.Unstructured) bool { + // Only delete direct children of the integration, otherwise we can affect the behavior of external controllers (i.e. Knative) + for _, o := range u.GetOwnerReferences() { + if o.Kind == v1.IntegrationKind && strings.HasPrefix(o.APIVersion, v1.SchemeGroupVersion.Group) && o.Name == e.Integration.Name { + return true + } + } + return false +} + +func (t *garbageCollectorTrait) getDeletableTypes(e *Environment) (map[schema.GroupVersionKind]struct{}, error) { // 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. discoveryClient, err := t.discoveryClient(e) if err != nil { - return nil, nil, err + return nil, err } resources, err := discoveryClient.ServerPreferredNamespacedResources() // 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, nil, err + return nil, err } - // We only take types that support the "delete" and "deletecollection" verbs, + // We only take types that support the "delete" verb, // to prevents from performing queries that we know are going to return "MethodNotAllowed". - return groupVersionKinds(discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"deletecollection"}}, resources)), - groupVersionKinds(discovery.FilteredBy(supportsDeleteVerbOnly{}, resources)), + return groupVersionKinds(discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"delete"}}, resources)), nil } @@ -240,14 +222,6 @@ func groupVersionKinds(rls []*metav1.APIResourceList) map[schema.GroupVersionKin return GVKs } -// supportsDeleteVerbOnly is a predicate matching a resource if it supports the delete verb, but not deletecollection. -type supportsDeleteVerbOnly struct{} - -func (p supportsDeleteVerbOnly) Match(groupVersion string, r *metav1.APIResource) bool { - verbs := sets.NewString([]string(r.Verbs)...) - return verbs.Has("delete") && !verbs.Has("deletecollection") -} - func (t *garbageCollectorTrait) discoveryClient(e *Environment) (discovery.DiscoveryInterface, error) { discoveryClientLock.Lock() defer discoveryClientLock.Unlock()