...

Source file src/edge-infra.dev/pkg/edge/linkerd/k8s/controllers/workloadinjection/workloads/ownerref.go

Documentation: edge-infra.dev/pkg/edge/linkerd/k8s/controllers/workloadinjection/workloads

     1  package workloads
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"reflect"
     8  
     9  	v1 "k8s.io/api/apps/v1"
    10  	corev1 "k8s.io/api/core/v1"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    13  	"k8s.io/apimachinery/pkg/runtime/schema"
    14  	"k8s.io/apimachinery/pkg/types"
    15  	"sigs.k8s.io/controller-runtime/pkg/client"
    16  
    17  	"edge-infra.dev/pkg/k8s/runtime/objectrestarter"
    18  )
    19  
    20  // getOwnerReference determines the workload object that owns the input object.
    21  // If a valid workload owner cant be found, an empty metav1.OwnerReference is returned.
    22  func getOwnerReference(m metav1.ObjectMeta) metav1.OwnerReference {
    23  	for i, ref := range m.OwnerReferences {
    24  		// either the kind must be restartable, a descendant of a kind that is
    25  		// restartable (eg, ReplicaSet are owned by Deployments, which are restartable)
    26  		if !objectrestarter.IsKindRestartable(ref.Kind) && ref.Kind != reflect.TypeOf(v1.ReplicaSet{}).Name() {
    27  			continue
    28  		}
    29  		return m.OwnerReferences[i]
    30  	}
    31  	return metav1.OwnerReference{}
    32  }
    33  
    34  // getReplicaSetOwnerReference determines the workload object that owns the input replicaSet.
    35  // For pods owned by a ReplicaSet we need to go one level up for the real owning type.
    36  // Technically ReplicaSets could be the highest level owning type, but it would
    37  // be an antipattern since the K8s API docs say they should be managed by
    38  // higher level workload types: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/#when-to-use-a-replicaset
    39  func getReplicaSetOwnerReference(ctx context.Context, c client.Client, pod corev1.Pod, ownerRef metav1.OwnerReference) (metav1.OwnerReference, error) {
    40  	replicaSet := &v1.ReplicaSet{}
    41  	if err := c.Get(ctx, types.NamespacedName{Name: ownerRef.Name, Namespace: pod.Namespace}, replicaSet); err != nil {
    42  		return metav1.OwnerReference{}, fmt.Errorf("failed to get owning replicaset: %w", err)
    43  	}
    44  	replicaSetOwnerRef := getOwnerReference(replicaSet.ObjectMeta)
    45  	if replicaSetOwnerRef == (metav1.OwnerReference{}) {
    46  		return metav1.OwnerReference{}, errors.New("failed to get owner ref for replicaset")
    47  	}
    48  	return replicaSetOwnerRef, nil
    49  }
    50  
    51  // getWorkloadFromOwnerReference returns the workload from the given ownerReference as an unstructured object.
    52  func getWorkloadFromOwnerReference(ctx context.Context, c client.Client, pod corev1.Pod, ownerRef metav1.OwnerReference) (*unstructured.Unstructured, error) {
    53  	gv, err := schema.ParseGroupVersion(ownerRef.APIVersion)
    54  	if err != nil {
    55  		return nil, fmt.Errorf("failed to parse apiVersion for owner ref: %w", err)
    56  	}
    57  	workload := &unstructured.Unstructured{}
    58  	workload.SetGroupVersionKind(gv.WithKind(ownerRef.Kind))
    59  	if err := c.Get(ctx, types.NamespacedName{Name: ownerRef.Name, Namespace: pod.Namespace}, workload); err != nil {
    60  		return nil, fmt.Errorf("failed to get owning workload %s/%s/%s: %w", ownerRef.Kind, pod.Namespace, ownerRef.Name, err)
    61  	}
    62  	return workload, nil
    63  }
    64  

View as plain text