| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- package scrape
- import (
- "testing"
- "github.com/opencost/opencost/core/pkg/clustercache"
- "github.com/opencost/opencost/core/pkg/source"
- "github.com/opencost/opencost/modules/collector-source/pkg/metric"
- )
- func Test_isDCGM(t *testing.T) {
- tests := map[string]struct {
- labels map[string]string
- want bool
- }{
- "nil": {
- labels: nil,
- want: false,
- },
- "empty": {
- labels: map[string]string{},
- want: false,
- },
- "app": {
- labels: map[string]string{
- "app": "dcgm-exporter",
- },
- want: true,
- },
- "app.kubernetes.io/name": {
- labels: map[string]string{
- "app.kubernetes.io/name": "dcgm-exporter",
- },
- want: true,
- },
- "app.kubernetes.io/component": {
- labels: map[string]string{
- "app.kubernetes.io/name": "dcgm-exporter",
- },
- want: true,
- },
- "invalid key": {
- labels: map[string]string{
- "invalid-key": "dcgm-exporter",
- },
- want: false,
- },
- "invalid value": {
- labels: map[string]string{
- "app.kubernetes.io/name": "dcgmExporter",
- },
- want: false,
- },
- "case insensitive": {
- labels: map[string]string{
- "app.kubernetes.io/name": "jhlkjhlkDcGm-eXpoRterlkjhlkuh",
- },
- want: true,
- },
- }
- for name, tt := range tests {
- t.Run(name, func(t *testing.T) {
- if got := isDCGM(tt.labels); got != tt.want {
- t.Errorf("isDCGM() = %v, want %v", got, tt.want)
- }
- })
- }
- }
- func Test_podUIDEnricher(t *testing.T) {
- cache := &clustercache.MockClusterCache{
- Pods: []*clustercache.Pod{
- {UID: "pod-uid-1", Name: "pod1", Namespace: "namespace1"},
- {UID: "pod-uid-2", Name: "pod2", Namespace: "namespace2"},
- },
- }
- tests := map[string]struct {
- labels map[string]string
- want map[string]string
- }{
- "resolves pod_uid from namespace and pod": {
- labels: map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "pod1",
- },
- want: map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "pod1",
- source.PodUIDLabel: "pod-uid-1",
- },
- },
- "unknown pod is left unset": {
- labels: map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "unknown-pod",
- },
- want: map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "unknown-pod",
- },
- },
- "pod name from wrong namespace is left unset": {
- labels: map[string]string{
- source.NamespaceLabel: "namespace2",
- source.PodLabel: "pod1",
- },
- want: map[string]string{
- source.NamespaceLabel: "namespace2",
- source.PodLabel: "pod1",
- },
- },
- "missing namespace label is left unset": {
- labels: map[string]string{
- source.PodLabel: "pod1",
- },
- want: map[string]string{
- source.PodLabel: "pod1",
- },
- },
- "missing pod label is left unset": {
- labels: map[string]string{
- source.NamespaceLabel: "namespace1",
- },
- want: map[string]string{
- source.NamespaceLabel: "namespace1",
- },
- },
- "nil labels is left untouched": {
- labels: nil,
- want: nil,
- },
- "existing non-empty pod_uid is left untouched": {
- labels: map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "pod1",
- source.PodUIDLabel: "already-set",
- },
- want: map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "pod1",
- source.PodUIDLabel: "already-set",
- },
- },
- }
- for name, tt := range tests {
- t.Run(name, func(t *testing.T) {
- enrich := podUIDEnricher(cache)
- updates := []metric.Update{{Labels: cloneLabels(tt.labels)}}
- enrich(updates)
- assertLabels(t, updates[0].Labels, tt.want)
- })
- }
- // A single call must correctly enrich every update in the batch, not just
- // the first, since updates are processed together rather than one at a time.
- t.Run("enriches every update in a multi-update batch", func(t *testing.T) {
- enrich := podUIDEnricher(cache)
- updates := []metric.Update{
- {Labels: map[string]string{source.NamespaceLabel: "namespace1", source.PodLabel: "pod1"}},
- {Labels: map[string]string{source.NamespaceLabel: "namespace2", source.PodLabel: "pod2"}},
- {Labels: map[string]string{source.NamespaceLabel: "namespace1", source.PodLabel: "unknown-pod"}},
- }
- enrich(updates)
- assertLabels(t, updates[0].Labels, map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "pod1",
- source.PodUIDLabel: "pod-uid-1",
- })
- assertLabels(t, updates[1].Labels, map[string]string{
- source.NamespaceLabel: "namespace2",
- source.PodLabel: "pod2",
- source.PodUIDLabel: "pod-uid-2",
- })
- assertLabels(t, updates[2].Labels, map[string]string{
- source.NamespaceLabel: "namespace1",
- source.PodLabel: "unknown-pod",
- })
- })
- t.Run("empty batch does not panic", func(t *testing.T) {
- enrich := podUIDEnricher(cache)
- enrich(nil)
- enrich([]metric.Update{})
- })
- }
- func cloneLabels(labels map[string]string) map[string]string {
- if labels == nil {
- return nil
- }
- clone := make(map[string]string, len(labels))
- for k, v := range labels {
- clone[k] = v
- }
- return clone
- }
- func assertLabels(t *testing.T, got, want map[string]string) {
- t.Helper()
- if len(got) != len(want) {
- t.Fatalf("got labels %v, want %v", got, want)
- }
- for k, v := range want {
- if got[k] != v {
- t.Errorf("label %q = %q, want %q", k, got[k], v)
- }
- }
- }
|