Skip to content

Commit

Permalink
podinfo: Populate workload info
Browse files Browse the repository at this point in the history
Signed-off-by: Michi Mutsuzaki <michi@isovalent.com>
  • Loading branch information
michi-covalent committed Sep 19, 2023
1 parent 5b25a7c commit 3d8f765
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 9 deletions.
9 changes: 8 additions & 1 deletion operator/podinfo/podinfo_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"reflect"

ciliumiov1alpha1 "github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
"github.com/cilium/tetragon/pkg/process"
"golang.org/x/exp/maps"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -87,13 +88,16 @@ func equal(pod *corev1.Pod, podInfo *ciliumiov1alpha1.PodInfo) bool {
Controller: &controller,
BlockOwnerDeletion: &blockOwnerDeletion,
}
workloadObject, workloadType := process.GetWorkloadMetaFromPod(pod)
return pod.Name == podInfo.Name &&
pod.Namespace == podInfo.Namespace &&
pod.Status.PodIP == podInfo.Status.PodIP &&
maps.Equal(pod.Annotations, podInfo.Annotations) &&
maps.Equal(pod.Labels, podInfo.Labels) &&
len(podInfo.OwnerReferences) == 1 &&
reflect.DeepEqual(podInfo.OwnerReferences[0], expectedOwnerReference)
reflect.DeepEqual(podInfo.OwnerReferences[0], expectedOwnerReference) &&
reflect.DeepEqual(podInfo.WorkloadObject, workloadObject) &&
reflect.DeepEqual(podInfo.WorkloadType, workloadType)
}

// hasAllRequiredFields checks if the necessary pod fields are available.
Expand All @@ -112,6 +116,7 @@ func generatePodInfo(pod *corev1.Pod) *ciliumiov1alpha1.PodInfo {
for _, podIP := range pod.Status.PodIPs {
podIPs = append(podIPs, ciliumiov1alpha1.PodIP{IP: podIP.IP})
}
workloadObject, workloadType := process.GetWorkloadMetaFromPod(pod)
controller := true
blockOwnerDeletion := true
return &ciliumiov1alpha1.PodInfo{
Expand All @@ -136,6 +141,8 @@ func generatePodInfo(pod *corev1.Pod) *ciliumiov1alpha1.PodInfo {
PodIP: pod.Status.PodIP,
PodIPs: podIPs,
},
WorkloadType: workloadType,
WorkloadObject: workloadObject,
}
}

Expand Down
22 changes: 22 additions & 0 deletions operator/podinfo/podinfo_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"testing"

ciliumv1alpha1 "github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
"github.com/cilium/tetragon/pkg/process"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -113,6 +114,7 @@ func TestGeneratePod(t *testing.T) {
for _, podIP := range pod.Status.PodIPs {
podIPs = append(podIPs, ciliumv1alpha1.PodIP{IP: podIP.IP})
}
workloadObject, workloadType := process.GetWorkloadMetaFromPod(pod)
expectedPodInfo := &ciliumv1alpha1.PodInfo{
ObjectMeta: metav1.ObjectMeta{
Name: pod.Name,
Expand All @@ -134,6 +136,8 @@ func TestGeneratePod(t *testing.T) {
PodIP: pod.Status.PodIP,
PodIPs: podIPs,
},
WorkloadType: workloadType,
WorkloadObject: workloadObject,
}
generatedPodInfo := generatePodInfo(pod)
assert.Equal(t, expectedPodInfo, generatedPodInfo, "Generated incorrect PodInfo corresponding to the pod")
Expand Down Expand Up @@ -244,5 +248,23 @@ func TestEqual(t *testing.T) {
pod.Annotations = getRandMap()
assert.False(t, equal(pod, podInfo), "Pod Annotations changed, still returning pod not changed")
})

t.Run("Pod owner references changed", func(t *testing.T) {
pod := randomPodGenerator()
controller, blockOwnerDeletion := true, true
podInfo := generatePodInfo(pod)
pod.GenerateName = "tetragon-"
pod.OwnerReferences = []metav1.OwnerReference{
{
APIVersion: "apps/v1",
Kind: "DaemonSet",
Name: "tetragon",
UID: "00000000-0000-0000-0000-000000000000",
Controller: &controller,
BlockOwnerDeletion: &blockOwnerDeletion,
},
}
assert.False(t, equal(pod, podInfo), "Pod owner references changed, still returning pod not changed")
})
})
}
50 changes: 50 additions & 0 deletions pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,56 @@ spec:
type: object
type: array
type: object
workloadObject:
description: Workload that created this pod.
properties:
annotations:
additionalProperties:
type: string
description: 'Annotations is an unstructured key value map stored
with a resource that may be set by external tools to store and retrieve
arbitrary metadata. They are not queryable and should be preserved
when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations'
type: object
labels:
additionalProperties:
type: string
description: 'Map of string keys and values that can be used to organize
and categorize (scope and select) objects. May match selectors of
replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels'
type: object
name:
description: 'Name must be unique within a namespace. Is required
when creating resources, although some resources may allow a client
to request the generation of an appropriate name automatically.
Name is primarily intended for creation idempotence and configuration
definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names'
type: string
namespace:
description: "Namespace defines the space within which each name must
be unique. An empty namespace is equivalent to the \"default\" namespace,
but \"default\" is the canonical representation. Not all objects
are required to be scoped to a namespace - the value of this field
for those objects will be empty. \n Must be a DNS_LABEL. Cannot
be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces"
type: string
type: object
workloadType:
description: Workload type (e.g. "Deployment", "Daemonset") that created
this pod.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource
this object represents. Servers may infer this from the endpoint
the client submits requests to. Cannot be updated. In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
type: object
type: object
served: true
storage: true
Expand Down
43 changes: 43 additions & 0 deletions pkg/k8s/apis/cilium.io/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,44 @@ type PodIP struct {
IP string `json:"IP,omitempty"`
}

// CompactObjectMeta is metadata that all persisted resources must have, which includes all objects
// users must create.
type CompactObjectMeta struct {
// Name must be unique within a namespace. Is required when creating resources, although
// some resources may allow a client to request the generation of an appropriate name
// automatically. Name is primarily intended for creation idempotence and configuration
// definition.
// Cannot be updated.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`

// Namespace defines the space within which each name must be unique. An empty namespace is
// equivalent to the "default" namespace, but "default" is the canonical representation.
// Not all objects are required to be scoped to a namespace - the value of this field for
// those objects will be empty.
//
// Must be a DNS_LABEL.
// Cannot be updated.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`

// Map of string keys and values that can be used to organize and categorize
// (scope and select) objects. May match selectors of replication controllers
// and services.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
// +optional
Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"`

// Annotations is an unstructured key value map stored with a resource that may be
// set by external tools to store and retrieve arbitrary metadata. They are not
// queryable and should be preserved when modifying objects.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"`
}

// +genclient
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand All @@ -283,6 +321,11 @@ type PodInfo struct {

Spec PodInfoSpec `json:"spec,omitempty"`
Status PodInfoStatus `json:"status,omitempty"`

// Workload type (e.g. "Deployment", "Daemonset") that created this pod.
WorkloadType metav1.TypeMeta `json:"workloadType,omitempty"`
// Workload that created this pod.
WorkloadObject CompactObjectMeta `json:"workloadObject,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
2 changes: 1 addition & 1 deletion pkg/k8s/apis/cilium.io/v1alpha1/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ package v1alpha1
// Used to determine if CRD needs to be updated in cluster
//
// Developers: Bump patch for each change in the CRD schema.
const CustomResourceDefinitionSchemaVersion = "0.12.3"
const CustomResourceDefinitionSchemaVersion = "0.12.4"
32 changes: 32 additions & 0 deletions pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions pkg/process/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,26 @@ import (
"regexp"
"strings"

"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var cronJobNameRegexp = regexp.MustCompile(`(.+)-\d{8,10}$`)

// GetWorkloadMetaFromPod heuristically derives workload metadata from the pod spec.
func getWorkloadMetaFromPod(pod *corev1.Pod) (metav1.ObjectMeta, metav1.TypeMeta) {
func GetWorkloadMetaFromPod(pod *corev1.Pod) (v1alpha1.CompactObjectMeta, metav1.TypeMeta) {
if pod == nil {
return metav1.ObjectMeta{}, metav1.TypeMeta{}
return v1alpha1.CompactObjectMeta{}, metav1.TypeMeta{}
}
// try to capture more useful namespace/name info for deployments, etc.
// TODO(dougreid): expand to enable lookup of OWNERs recursively a la kubernetesenv
deployMeta := pod.ObjectMeta
deployMeta.ManagedFields = nil
deployMeta.OwnerReferences = nil
deployMeta := v1alpha1.CompactObjectMeta{
Name: pod.GetObjectMeta().GetName(),
Namespace: pod.GetObjectMeta().GetNamespace(),
Labels: pod.GetObjectMeta().GetLabels(),
Annotations: pod.GetObjectMeta().GetAnnotations(),
}

typeMetadata := metav1.TypeMeta{
Kind: "Pod",
Expand Down Expand Up @@ -89,6 +93,6 @@ func getWorkloadMetaFromPod(pod *corev1.Pod) (metav1.ObjectMeta, metav1.TypeMeta
}

func getWorkloadNameFromPod(pod *corev1.Pod) string {
objMeta, _ := getWorkloadMetaFromPod(pod)
objMeta, _ := GetWorkloadMetaFromPod(pod)
return objMeta.Name
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3d8f765

Please sign in to comment.