This is an automated email from the ASF dual-hosted git repository. astefanutti pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit ad31c64b3faac968d28b7d5d87f26d86ce756f37 Author: Antonin Stefanutti <anto...@stefanutti.fr> AuthorDate: Wed Oct 9 14:53:03 2019 +0200 chore(trait): Encapsulate GC trait specific methods --- pkg/trait/gc.go | 83 ++++++++++++++++++++++++++++++++++++++++++--- pkg/util/kubernetes/util.go | 81 ------------------------------------------- 2 files changed, 79 insertions(+), 85 deletions(-) diff --git a/pkg/trait/gc.go b/pkg/trait/gc.go index d104db1..8b29e74 100644 --- a/pkg/trait/gc.go +++ b/pkg/trait/gc.go @@ -21,14 +21,19 @@ import ( "context" "fmt" "strconv" + "strings" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/discovery" - "sigs.k8s.io/controller-runtime/pkg/client" + controller "sigs.k8s.io/controller-runtime/pkg/client" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" - "github.com/apache/camel-k/pkg/util/kubernetes" + "github.com/apache/camel-k/pkg/client" + "github.com/apache/camel-k/pkg/util" ) type garbageCollectorTrait struct { @@ -98,7 +103,7 @@ func (t *garbageCollectorTrait) garbageCollectResources(e *Environment) { fmt.Sprintf("camel.apache.org/generation<%d", e.Integration.GetGeneration()), } - resources, err := kubernetes.LookUpResources(context.TODO(), e.Client, e.Integration.Namespace, selectors) + resources, err := lookUpResources(context.TODO(), e.Client, e.Integration.Namespace, selectors) if err != nil { t.L.ForIntegration(e.Integration).Errorf(err, "cannot collect older generation resources") return @@ -108,7 +113,7 @@ func (t *garbageCollectorTrait) garbageCollectResources(e *Environment) { for _, resource := range resources { // pin the resource resource := resource - err = e.Client.Delete(context.TODO(), &resource, client.PropagationPolicy(metav1.DeletePropagationBackground)) + err = e.Client.Delete(context.TODO(), &resource, controller.PropagationPolicy(metav1.DeletePropagationBackground)) if err != nil { // The resource may have already been deleted if !k8serrors.IsNotFound(err) { @@ -119,3 +124,73 @@ func (t *garbageCollectorTrait) garbageCollectResources(e *Environment) { } } } +func lookUpResources(ctx context.Context, client client.Client, namespace string, selectors []string) ([]unstructured.Unstructured, error) { + // We only take types that support the "create" and "list" verbs as: + // - they have to be created to be deleted :) so that excludes read-only + // resources, e.g., aggregated APIs + // - they are going to be iterated and a list query with labels selector + // is performed for each of them. That prevents from performing queries + // that we know are going to return "MethodNotAllowed". + types, err := getDiscoveryTypesWithVerbs(client, []string{"create", "list"}) + if err != nil { + return nil, err + } + + selector, err := labels.Parse(strings.Join(selectors, ",")) + if err != nil { + return nil, err + } + + res := make([]unstructured.Unstructured, 0) + + for _, t := range types { + options := controller.ListOptions{ + Namespace: namespace, + LabelSelector: selector, + Raw: &metav1.ListOptions{ + TypeMeta: t, + }, + } + list := unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "apiVersion": t.APIVersion, + "kind": t.Kind, + }, + } + if err := client.List(ctx, &options, &list); err != nil { + if k8serrors.IsNotFound(err) || k8serrors.IsForbidden(err) { + continue + } + return nil, err + } + + res = append(res, list.Items...) + } + return res, nil +} + +func getDiscoveryTypesWithVerbs(client client.Client, verbs []string) ([]metav1.TypeMeta, error) { + resources, err := client.Discovery().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, err + } + + types := make([]metav1.TypeMeta, 0) + for _, resource := range resources { + for _, r := range resource.APIResources { + if len(verbs) > 0 && !util.StringSliceContains(r.Verbs, verbs) { + // Do not return the type if it does not support the provided verbs + continue + } + types = append(types, metav1.TypeMeta{ + Kind: r.Kind, + APIVersion: resource.GroupVersion, + }) + } + } + + return types, nil +} diff --git a/pkg/util/kubernetes/util.go b/pkg/util/kubernetes/util.go index 7ac67e0..332630c 100644 --- a/pkg/util/kubernetes/util.go +++ b/pkg/util/kubernetes/util.go @@ -20,23 +20,15 @@ package kubernetes import ( "context" "fmt" - "strings" corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/json" - "k8s.io/client-go/discovery" - k8sclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/client" - "github.com/apache/camel-k/pkg/util" - yaml2 "gopkg.in/yaml.v2" ) @@ -209,79 +201,6 @@ func GetService(context context.Context, client k8sclient.Reader, name string, n return &answer, nil } -// GetDiscoveryTypesWithVerbs -- -func GetDiscoveryTypesWithVerbs(client client.Client, verbs []string) ([]metav1.TypeMeta, error) { - resources, err := client.Discovery().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, err - } - - types := make([]metav1.TypeMeta, 0) - for _, resource := range resources { - for _, r := range resource.APIResources { - if len(verbs) > 0 && !util.StringSliceContains(r.Verbs, verbs) { - // Do not return the type if it does not support the provided verbs - continue - } - types = append(types, metav1.TypeMeta{ - Kind: r.Kind, - APIVersion: resource.GroupVersion, - }) - } - } - - return types, nil -} - -// LookUpResources -- -func LookUpResources(ctx context.Context, client client.Client, namespace string, selectors []string) ([]unstructured.Unstructured, error) { - // We only take types that support the "create" and "list" verbs as: - // - they have to be created to be deleted :) so that excludes read-only - // resources, e.g., aggregated APIs - // - they are going to be iterated and a list query with labels selector - // is performed for each of them. That prevents from performing queries - // that we know are going to return "MethodNotAllowed". - types, err := GetDiscoveryTypesWithVerbs(client, []string{"create", "list"}) - if err != nil { - return nil, err - } - - selector, err := labels.Parse(strings.Join(selectors, ",")) - if err != nil { - return nil, err - } - - res := make([]unstructured.Unstructured, 0) - - for _, t := range types { - options := k8sclient.ListOptions{ - Namespace: namespace, - LabelSelector: selector, - Raw: &metav1.ListOptions{ - TypeMeta: t, - }, - } - list := unstructured.UnstructuredList{ - Object: map[string]interface{}{ - "apiVersion": t.APIVersion, - "kind": t.Kind, - }, - } - if err := client.List(ctx, &options, &list); err != nil { - if k8serrors.IsNotFound(err) || k8serrors.IsForbidden(err) { - continue - } - return nil, err - } - - res = append(res, list.Items...) - } - return res, nil -} - // GetSecretRefValue returns the value of a secret in the supplied namespace -- func GetSecretRefValue(ctx context.Context, client k8sclient.Reader, namespace string, selector *corev1.SecretKeySelector) (string, error) { secret, err := GetSecret(ctx, client, selector.Name, namespace)