Skip to content

Commit

Permalink
test: add unit test for pod enhancer (#73)
Browse files Browse the repository at this point in the history
* add unit test for pod enhancer

* Make aliasing more explicit

* feature: allow object manifest to define custom DSN (#72)

* allow custom dsn in manifest

* fix errors of sending to wrong projects

* clients inherit old options with only dsn changed

* change transport mock to remove last event

* refactor dsn code

* fix event watcher to pass unit test

* perform minor code cleanup

* add flag for custom dsn

* add minor changes to sentry dsn data

* downgrade client-go version

* fix dependency issues

---------

Co-authored-by: Anton Ovchinnikov <anton@tonyo.info>
  • Loading branch information
Jiahui-Zhang-20 and tonyo authored Dec 14, 2023
1 parent da92dca commit 9086675
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 7 deletions.
11 changes: 8 additions & 3 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,21 @@ import (

type clientsetCtxKey struct{}

func setClientsetOnContext(ctx context.Context, clientset *kubernetes.Clientset) context.Context {
// Note: we do not use kubernetes.Clientset type directly, to enable mocking via "k8s.io/client-go/kubernetes/fake"
// package. A type alias is introduced to avoid confusion: "kubernetes.Interface" is actually a clientset.Interface, and
// not a generic interface for Kubernetes resources.
type ClientsetInterface = kubernetes.Interface

func setClientsetOnContext(ctx context.Context, clientset ClientsetInterface) context.Context {
return context.WithValue(ctx, clientsetCtxKey{}, clientset)
}

func getClientsetFromContext(ctx context.Context) (*kubernetes.Clientset, error) {
func getClientsetFromContext(ctx context.Context) (ClientsetInterface, error) {
val := ctx.Value(clientsetCtxKey{})
if val == nil {
return nil, fmt.Errorf("no clientset present on context")
}
if clientset, ok := val.(*kubernetes.Clientset); ok {
if clientset, ok := val.(ClientsetInterface); ok {
return clientset, nil
} else {
return nil, fmt.Errorf("cannot convert clientset value from context")
Expand Down
102 changes: 102 additions & 0 deletions enhancers_pod_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package main

import (
"context"
"testing"

"github.com/getsentry/sentry-go"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)

func TestRunPodEnhancer(t *testing.T) {

// Create empty context
ctx := context.Background()
// Create simple fake client
fakeClientset := fake.NewSimpleClientset()
// Create pod object with an error status
podObj := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "TestRunPodEnhancerPod",
Namespace: "TestRunPodEnhancerNamespace",
},
Spec: corev1.PodSpec{
NodeName: "TestRunPodEnhancerNode",
},
Status: corev1.PodStatus{
ContainerStatuses: []corev1.ContainerStatus{
{
Name: "FakeDnsLabel",
State: corev1.ContainerState{
Terminated: &corev1.ContainerStateTerminated{
ExitCode: 1,
Reason: "Fake Reason: TestRunPodEnhancerEvent",
Message: "Fake Message: TestRunPodEnhancerEvent",
},
},
},
},
},
}
_, err := fakeClientset.CoreV1().Pods("TestRunPodEnhancerNamespace").Create(context.TODO(), podObj, metav1.CreateOptions{})
if err != nil {
t.Fatalf("error injecting pod add: %v", err)
}
ctx = setClientsetOnContext(ctx, fakeClientset)
objRef := &corev1.ObjectReference{
Name: "TestRunPodEnhancerPod",
Namespace: "TestRunPodEnhancerNamespace",
}

// Create empty scope
scope := sentry.NewScope()
// Create empty event
event := sentry.NewEvent()
// Add event message
event.Message = "This event is for TestRunPodEnhancer"
// Call pod enhancer to modify scope and event
err = runPodEnhancer(ctx, objRef, nil, scope, event)
if err != nil {
t.Errorf("pod enhancer returned an error: %v", err)
}

// Apply the scope to the event
// so we can check the tags
scope.ApplyToEvent(event, nil)

expectedTags := map[string]string{
"node_name": "TestRunPodEnhancerNode",
}
// the test fails if any tag key, value pair does not match
for key, val := range expectedTags {
if event.Tags[key] != expectedTags[key] {
t.Errorf("For Sentry tag with key [%s], received \"%s\", wanted \"%s\"", key, event.Tags[key], val)
}
}
expectedFingerprints := []string{
"This event is for TestRunPodEnhancer",
"TestRunPodEnhancerPod",
}

// The test fails if any tag key, value pair does not match
var found bool
for _, expectedFingerprint := range expectedFingerprints {
found = false
for _, fingerprint := range event.Fingerprint {
if expectedFingerprint == fingerprint {
found = true
}
}
if !found {
t.Errorf("The fingerprint slice does not contain the expected fingerprint: %s", expectedFingerprint)
}
}

// Check message is changed to include pod name
expectedMessage := "TestRunPodEnhancerPod: This event is for TestRunPodEnhancer"
if event.Message != expectedMessage {
t.Errorf("For event message, received \"%s\", wanted \"%s\"", event.Message, expectedMessage)
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
Expand All @@ -33,6 +34,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
Expand Down
9 changes: 5 additions & 4 deletions watcher_pods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ func TestHandlePodWatchEvent(t *testing.T) {
Object: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "TestHandlePodWatchEventPod",
Namespace: "TestHandlePodWatchEventNameSpace",
Namespace: "TestHandlePodWatchEventNamespace",
},
Status: corev1.PodStatus{
ContainerStatuses: []corev1.ContainerStatus{
{
Name: "fake_DNS_Label",
Name: "FakeDnsLabel",
State: corev1.ContainerState{
Terminated: &corev1.ContainerStateTerminated{
ExitCode: 1,
Expand Down Expand Up @@ -86,9 +86,10 @@ func TestHandlePodWatchEvent(t *testing.T) {

// Check that the tags of event are set correctly by the innermost scope
// corresponding to the creation of the Sentry event
expectedTags := map[string]string{"container_name": "fake_DNS_Label",
expectedTags := map[string]string{
"container_name": "FakeDnsLabel",
"event_source_component": "x-pod-controller",
"namespace": "TestHandlePodWatchEventNameSpace",
"namespace": "TestHandlePodWatchEventNamespace",
"pod_name": "TestHandlePodWatchEventPod",
"reason": "Fake Reason: TestHandlePodWatchEvent",
"watcher_name": "pods"}
Expand Down

0 comments on commit 9086675

Please sign in to comment.