Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

podinfo: Populate workload info #1493

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
})
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,32 @@ spec:
type: object
type: array
type: object
workloadObject:
description: Workload that created this pod.
properties:
name:
description: Name of the object.
type: string
namespace:
description: Namespace of this object.
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
16 changes: 16 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,17 @@ type PodIP struct {
IP string `json:"IP,omitempty"`
}

// WorkloadObjectMeta is metadata associated with workloads that create pods.
type WorkloadObjectMeta struct {
// Name of the object.
// +optional
Name string `json:"name,omitempty"`

// Namespace of this object.
// +optional
Namespace string `json:"namespace,omitempty"`
}

// +genclient
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand All @@ -283,6 +294,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 WorkloadObjectMeta `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"
18 changes: 18 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.

15 changes: 8 additions & 7 deletions pkg/process/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,24 @@ 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.WorkloadObjectMeta, metav1.TypeMeta) {
if pod == nil {
return metav1.ObjectMeta{}, metav1.TypeMeta{}
return v1alpha1.WorkloadObjectMeta{}, 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.WorkloadObjectMeta{
Name: pod.GetObjectMeta().GetName(),
Namespace: pod.GetObjectMeta().GetNamespace(),
}

typeMetadata := metav1.TypeMeta{
Kind: "Pod",
Expand Down Expand Up @@ -65,7 +67,6 @@ func getWorkloadMetaFromPod(pod *corev1.Pod) (metav1.ObjectMeta, metav1.TypeMeta
// https://github.com/openshift/library-go/blob/7a65fdb398e28782ee1650959a5e0419121e97ae/pkg/apps/appsutil/const.go#L25
deployMeta.Name = pod.Labels["deploymentconfig"]
typeMetadata.Kind = "DeploymentConfig"
delete(deployMeta.Labels, "deploymentconfig")
} else if typeMetadata.Kind == "Job" {
// If job name suffixed with `-<digit-timestamp>`, where the length of digit timestamp is 8~10,
// trim the suffix and set kind to cron job.
Expand All @@ -89,6 +90,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.

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

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

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