master
go 204 lines 6.09 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package scrape
4
5 import (
6 "testing"
7
8 "github.com/stretchr/testify/require"
9 "github.com/vmware/govmomi/vim25/types"
10 vsantypes "github.com/vmware/govmomi/vsan/types"
11
12 rs "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/resources"
13 )
14
15 func TestParseVSANEntityMetrics(t *testing.T) {
16 tests := map[string]struct {
17 raw []vsantypes.VsanPerfEntityMetricCSV
18 specs map[string]vsanMetricSpec
19 want map[string]VSANEntityMetrics
20 }{
21 "cluster latest values and rates": {
22 raw: []vsantypes.VsanPerfEntityMetricCSV{{
23 EntityRefId: "cluster-domclient:cluster-uuid",
24 Value: []vsantypes.VsanPerfMetricSeriesCSV{
25 {
26 MetricId: vsantypes.VsanPerfMetricId{Label: "iopsRead"},
27 Values: "10,20",
28 },
29 {
30 MetricId: vsantypes.VsanPerfMetricId{Label: "throughputRead", MetricsCollectInterval: 20},
31 Values: "100,200",
32 },
33 {
34 MetricId: vsantypes.VsanPerfMetricId{Label: "congestion"},
35 Values: "300",
36 },
37 {
38 MetricId: vsantypes.VsanPerfMetricId{Label: "ignored"},
39 Values: "999",
40 },
41 },
42 }},
43 want: map[string]VSANEntityMetrics{
44 "cluster-uuid": {
45 "read_operations": 20,
46 "read_throughput": 10,
47 "congestions": 1,
48 },
49 },
50 },
51 "host label set follows vSAN API labels": {
52 specs: vsanHostMetricSpecs,
53 raw: []vsantypes.VsanPerfEntityMetricCSV{{
54 EntityRefId: "host-domclient:host-uuid",
55 Value: []vsantypes.VsanPerfMetricSeriesCSV{
56 {
57 MetricId: vsantypes.VsanPerfMetricId{Label: "throughputRead", MetricsCollectInterval: 300},
58 Values: "600",
59 },
60 {
61 MetricId: vsantypes.VsanPerfMetricId{Label: "latencyAvgRead"},
62 Values: "700",
63 },
64 {
65 MetricId: vsantypes.VsanPerfMetricId{Label: "clientCacheHitRate"},
66 Values: "85",
67 },
68 {
69 MetricId: vsantypes.VsanPerfMetricId{Label: "congestion", MetricsCollectInterval: 300},
70 Values: "900",
71 },
72 },
73 }},
74 want: map[string]VSANEntityMetrics{
75 "host-uuid": {
76 "read_throughput": 2,
77 "read_latency": 700,
78 "cache_hit_rate": 85,
79 "congestions": 3,
80 },
81 },
82 },
83 "vm label set uses latencyRead latencyWrite": {
84 specs: vsanVMMetricSpecs,
85 raw: []vsantypes.VsanPerfEntityMetricCSV{{
86 EntityRefId: "virtual-machine:vm-uuid",
87 Value: []vsantypes.VsanPerfMetricSeriesCSV{
88 {
89 MetricId: vsantypes.VsanPerfMetricId{Label: "throughputWrite", MetricsCollectInterval: 300},
90 Values: "1200",
91 },
92 {
93 MetricId: vsantypes.VsanPerfMetricId{Label: "latencyRead"},
94 Values: "11",
95 },
96 {
97 MetricId: vsantypes.VsanPerfMetricId{Label: "latencyWrite"},
98 Values: "12",
99 },
100 {
101 MetricId: vsantypes.VsanPerfMetricId{Label: "latencyAvgRead"},
102 Values: "13",
103 },
104 },
105 }},
106 want: map[string]VSANEntityMetrics{
107 "vm-uuid": {
108 "write_throughput": 4,
109 "read_latency": 11,
110 "write_latency": 12,
111 },
112 },
113 },
114 "sample info aligns series to the latest sample bucket": {
115 raw: []vsantypes.VsanPerfEntityMetricCSV{{
116 EntityRefId: "cluster-domclient:cluster-uuid",
117 SampleInfo: "2026-05-09 10:00:00,2026-05-09 10:05:00",
118 Value: []vsantypes.VsanPerfMetricSeriesCSV{
119 {
120 MetricId: vsantypes.VsanPerfMetricId{Label: "iopsRead"},
121 Values: "20,",
122 },
123 {
124 MetricId: vsantypes.VsanPerfMetricId{Label: "throughputRead", MetricsCollectInterval: 20},
125 Values: "100,200",
126 },
127 },
128 }},
129 want: map[string]VSANEntityMetrics{
130 "cluster-uuid": {
131 "read_throughput": 10,
132 },
133 },
134 },
135 "empty value skipped": {
136 raw: []vsantypes.VsanPerfEntityMetricCSV{{
137 EntityRefId: "host-domclient:host-uuid",
138 Value: []vsantypes.VsanPerfMetricSeriesCSV{{
139 MetricId: vsantypes.VsanPerfMetricId{Label: "iopsRead"},
140 Values: "",
141 }},
142 }},
143 want: map[string]VSANEntityMetrics{},
144 },
145 }
146
147 for name, tc := range tests {
148 t.Run(name, func(t *testing.T) {
149 specs := tc.specs
150 if specs == nil {
151 specs = vsanClusterMetricSpecs
152 }
153 got, err := parseVSANEntityMetrics(tc.raw, specs)
154 require.NoError(t, err)
155 require.Equal(t, tc.want, got)
156 })
157 }
158 }
159
160 func TestParseVSANEntityMetricsSkipsEntityWithoutUUID(t *testing.T) {
161 got, err := parseVSANEntityMetrics([]vsantypes.VsanPerfEntityMetricCSV{
162 {
163 EntityRefId: "cluster-domclient",
164 Value: []vsantypes.VsanPerfMetricSeriesCSV{{
165 MetricId: vsantypes.VsanPerfMetricId{Label: "iopsRead"},
166 Values: "1",
167 }},
168 },
169 {
170 EntityRefId: "cluster-domclient:cluster-uuid",
171 Value: []vsantypes.VsanPerfMetricSeriesCSV{{
172 MetricId: vsantypes.VsanPerfMetricId{Label: "iopsRead"},
173 Values: "2",
174 }},
175 },
176 }, vsanClusterMetricSpecs)
177
178 require.NoError(t, err)
179 require.Equal(t, map[string]VSANEntityMetrics{
180 "cluster-uuid": {"read_operations": 2},
181 }, got)
182 }
183
184 func TestVSANQueryIDsUseConcreteDiscoveredEntities(t *testing.T) {
185 cluster := &rs.Cluster{
186 ID: "domain-c1",
187 VSANUUID: "cluster-uuid",
188 Ref: types.ManagedObjectReference{Type: "ClusterComputeResource", Value: "domain-c1"},
189 }
190 hosts := rs.Hosts{
191 "host-1": {ID: "host-1", VSANNodeUUID: "node-2", Hier: rs.HostHierarchy{Cluster: rs.HierarchyValue{ID: "domain-c1"}}},
192 "host-2": {ID: "host-2", VSANNodeUUID: "node-1", Hier: rs.HostHierarchy{Cluster: rs.HierarchyValue{ID: "domain-c1"}}},
193 "host-3": {ID: "host-3", VSANNodeUUID: "node-3", Hier: rs.HostHierarchy{Cluster: rs.HierarchyValue{ID: "domain-c2"}}},
194 }
195 vms := rs.VMs{
196 "vm-1": {ID: "vm-1", InstanceUUID: "vm-2", Hier: rs.VMHierarchy{Cluster: rs.HierarchyValue{ID: "domain-c1"}}},
197 "vm-2": {ID: "vm-2", InstanceUUID: "vm-1", Hier: rs.VMHierarchy{Cluster: rs.HierarchyValue{ID: "domain-c1"}}},
198 "vm-3": {ID: "vm-3", InstanceUUID: "vm-3", Hier: rs.VMHierarchy{Cluster: rs.HierarchyValue{ID: "domain-c2"}}},
199 }
200
201 require.Equal(t, []string{"cluster-domclient:cluster-uuid"}, vsanClusterQueryIDs(cluster))
202 require.Equal(t, []string{"host-domclient:node-1", "host-domclient:node-2"}, vsanHostQueryIDs(cluster, hosts))
203 require.Equal(t, []string{"virtual-machine:vm-1", "virtual-machine:vm-2"}, vsanVMQueryIDs(cluster, vms))
204 }