Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/operator/hierarchy/hierarchy_test.go
4094 views
1
//go:build !nonetwork && !nodocker && !race
2
3
package hierarchy
4
5
import (
6
"context"
7
"testing"
8
"time"
9
10
"github.com/go-kit/log"
11
"github.com/grafana/agent/pkg/util/k8s"
12
"github.com/stretchr/testify/require"
13
v1 "k8s.io/api/core/v1"
14
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15
"k8s.io/apimachinery/pkg/labels"
16
"k8s.io/apimachinery/pkg/types"
17
"k8s.io/client-go/util/workqueue"
18
"sigs.k8s.io/controller-runtime/pkg/event"
19
)
20
21
// TestNotifier tests that notifier properly handles events for changed
22
// objects.
23
func TestNotifier(t *testing.T) {
24
l := log.NewNopLogger()
25
26
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
27
defer cancel()
28
29
cluster, err := k8s.NewCluster(ctx, k8s.Options{})
30
require.NoError(t, err)
31
defer cluster.Stop()
32
33
cli := cluster.Client()
34
35
// Tests will rely on a namespace existing, so let's create a namespace with
36
// some labels.
37
testNs := v1.Namespace{
38
TypeMeta: metav1.TypeMeta{
39
APIVersion: "v1",
40
Kind: "Namespace",
41
},
42
ObjectMeta: metav1.ObjectMeta{
43
Name: "enqueue-test",
44
Labels: map[string]string{"foo": "bar"},
45
},
46
}
47
err = cli.Create(ctx, &testNs)
48
require.NoError(t, err)
49
50
testPod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{
51
Name: "test-pod",
52
Namespace: "enqueue-test",
53
Labels: map[string]string{"fizz": "buzz"},
54
}}
55
56
tt := []struct {
57
name string
58
sel Selector
59
expectEnqueue bool
60
}{
61
{
62
name: "no watchers",
63
sel: nil,
64
expectEnqueue: false,
65
},
66
{
67
name: "matches watcher",
68
sel: &LabelsSelector{
69
NamespaceName: "enqueue-test",
70
NamespaceLabels: parseSelector(t, "foo in (bar)"),
71
Labels: parseSelector(t, "fizz in (buzz)"),
72
},
73
expectEnqueue: true,
74
},
75
{
76
name: "matches watcher with explicit namespace",
77
sel: &LabelsSelector{
78
NamespaceName: "enqueue-test",
79
Labels: parseSelector(t, "fizz in (buzz)"),
80
},
81
expectEnqueue: true,
82
},
83
{
84
name: "bad namespace name selector",
85
sel: &LabelsSelector{
86
NamespaceName: "default",
87
Labels: labels.Everything(),
88
},
89
expectEnqueue: false,
90
},
91
{
92
name: "bad namespace label selector",
93
sel: &LabelsSelector{
94
NamespaceName: "enqueue-test",
95
NamespaceLabels: parseSelector(t, "foo notin (bar)"),
96
Labels: labels.Everything(),
97
},
98
expectEnqueue: false,
99
},
100
{
101
name: "bad label selector",
102
sel: &LabelsSelector{
103
NamespaceName: "default",
104
NamespaceLabels: labels.Everything(),
105
Labels: parseSelector(t, "fizz notin (buzz)"),
106
},
107
expectEnqueue: false,
108
},
109
}
110
111
for _, tc := range tt {
112
t.Run(tc.name, func(t *testing.T) {
113
limiter := workqueue.DefaultControllerRateLimiter()
114
q := workqueue.NewRateLimitingQueue(limiter)
115
116
notifier := NewNotifier(l, cli)
117
118
if tc.sel != nil {
119
err := notifier.Notify(Watcher{
120
Object: &v1.Pod{},
121
Owner: types.NamespacedName{Name: "watcher", Namespace: "enqueue-test"},
122
Selector: tc.sel,
123
})
124
require.NoError(t, err)
125
}
126
127
e := notifier.EventHandler()
128
e.Create(event.CreateEvent{Object: testPod}, q)
129
if tc.expectEnqueue {
130
require.Equal(t, 1, q.Len(), "expected change enqueue")
131
} else {
132
require.Equal(t, 0, q.Len(), "no changes should have been enqueued")
133
}
134
})
135
}
136
}
137
138
func parseSelector(t *testing.T, selector string) labels.Selector {
139
t.Helper()
140
s, err := labels.Parse(selector)
141
require.NoError(t, err)
142
return s
143
}
144
145