master
go 224 lines 6.22 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package scrape
4
5 import (
6 "bytes"
7 "crypto/tls"
8 "errors"
9 "net/url"
10 "strings"
11 "testing"
12 "time"
13
14 "github.com/stretchr/testify/assert"
15 "github.com/stretchr/testify/require"
16 "github.com/vmware/govmomi/performance"
17 "github.com/vmware/govmomi/simulator"
18 "github.com/vmware/govmomi/vim25/types"
19 vsantypes "github.com/vmware/govmomi/vsan/types"
20
21 "github.com/netdata/netdata/go/plugins/logger"
22 "github.com/netdata/netdata/go/plugins/pkg/tlscfg"
23 "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/client"
24 "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/discover"
25 rs "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/resources"
26 )
27
28 func TestScraper_calcMaxQuery(t *testing.T) {
29 tests := map[string]struct {
30 version string
31 want int
32 }{
33 "vcenter 5.5": {version: "5.5.0", want: 64},
34 "vcenter 6.0": {version: "6.0.0", want: 64},
35 "vcenter 6.5": {version: "6.5.0", want: 256},
36 "vcenter 7.0": {version: "7.0.0", want: 256},
37 "vcenter 8.0": {version: "8.0.0", want: 256},
38 "unparsable version": {version: "not-a-version", want: 64},
39 }
40
41 for name, tt := range tests {
42 t.Run(name, func(t *testing.T) {
43 s := New(mockClient{version: tt.version})
44 assert.Equal(t, tt.want, s.maxQuery)
45 })
46 }
47 }
48
49 func TestScraper_ScrapeInventoryPerf(t *testing.T) {
50 tests := map[string]struct {
51 scrape func(*Scraper, *rs.Resources) []performance.EntityMetric
52 want func(*rs.Resources) int
53 }{
54 "VMs": {
55 scrape: func(s *Scraper, res *rs.Resources) []performance.EntityMetric { return s.ScrapeVMs(res.VMs) },
56 want: func(res *rs.Resources) int { return len(res.VMs) },
57 },
58 "hosts": {
59 scrape: func(s *Scraper, res *rs.Resources) []performance.EntityMetric { return s.ScrapeHosts(res.Hosts) },
60 want: func(res *rs.Resources) int { return len(res.Hosts) },
61 },
62 }
63
64 for name, tc := range tests {
65 t.Run(name, func(t *testing.T) {
66 s, res, teardown := prepareScraper(t)
67 defer teardown()
68
69 metrics := tc.scrape(s, res)
70 assert.Len(t, metrics, tc.want(res))
71 })
72 }
73 }
74
75 func TestScraper_ScrapeMetricsErrorIsRateLimited(t *testing.T) {
76 var buf bytes.Buffer
77 s := New(mockClient{
78 version: "8.0.0",
79 perfErr: errors.New("query failed"),
80 })
81 s.Logger = logger.NewWithWriter(&buf)
82 hosts := rs.Hosts{
83 "host-1": &rs.Host{
84 ID: "host-1",
85 PowerState: string(types.HostSystemPowerStatePoweredOn),
86 MetricList: performance.MetricList{
87 {CounterId: 1},
88 },
89 Ref: types.ManagedObjectReference{Type: "HostSystem", Value: "host-1"},
90 },
91 }
92
93 s.ScrapeHosts(hosts)
94 s.ScrapeHosts(hosts)
95
96 assert.Equal(t, 1, strings.Count(buf.String(), "scrape vSphere performance metrics"))
97 }
98
99 func TestScraper_ScrapeVSANRecordsEmptyHealthAsUnknown(t *testing.T) {
100 s := New(mockClient{version: "8.0.0"})
101 clusters := rs.Clusters{
102 "domain-c1": &rs.Cluster{
103 ID: "domain-c1",
104 VSANEnabled: true,
105 VSANUUID: "cluster-uuid",
106 Ref: types.ManagedObjectReference{Type: "ClusterComputeResource", Value: "domain-c1"},
107 },
108 }
109
110 got := s.ScrapeVSAN(clusters, nil, nil)
111
112 require.Contains(t, got.Health, "domain-c1")
113 assert.Empty(t, got.Health["domain-c1"])
114 }
115
116 func Test_newPerfQuerySpecsSkipsNonPoweredResources(t *testing.T) {
117 tests := map[string]struct {
118 query func() []types.PerfQuerySpec
119 want string
120 }{
121 "hosts": {
122 query: func() []types.PerfQuerySpec {
123 return newHostsPerfQuerySpecs(rs.Hosts{
124 "host-1": &rs.Host{
125 ID: "host-1",
126 PowerState: string(types.HostSystemPowerStatePoweredOn),
127 MetricList: performance.MetricList{{CounterId: 1}},
128 Ref: types.ManagedObjectReference{Type: "HostSystem", Value: "host-1"},
129 },
130 "host-2": &rs.Host{
131 ID: "host-2",
132 PowerState: string(types.HostSystemPowerStatePoweredOff),
133 MetricList: performance.MetricList{{CounterId: 1}},
134 Ref: types.ManagedObjectReference{Type: "HostSystem", Value: "host-2"},
135 },
136 })
137 },
138 want: "host-1",
139 },
140 "VMs": {
141 query: func() []types.PerfQuerySpec {
142 return newVMsPerfQuerySpecs(rs.VMs{
143 "vm-1": &rs.VM{
144 ID: "vm-1",
145 PowerState: string(types.VirtualMachinePowerStatePoweredOn),
146 MetricList: performance.MetricList{{CounterId: 1}},
147 Ref: types.ManagedObjectReference{Type: "VirtualMachine", Value: "vm-1"},
148 },
149 "vm-2": &rs.VM{
150 ID: "vm-2",
151 PowerState: string(types.VirtualMachinePowerStateSuspended),
152 MetricList: performance.MetricList{{CounterId: 1}},
153 Ref: types.ManagedObjectReference{Type: "VirtualMachine", Value: "vm-2"},
154 },
155 })
156 },
157 want: "vm-1",
158 },
159 }
160
161 for name, tc := range tests {
162 t.Run(name, func(t *testing.T) {
163 pqs := tc.query()
164
165 require.Len(t, pqs, 1)
166 assert.Equal(t, tc.want, pqs[0].Entity.Value)
167 })
168 }
169 }
170
171 func prepareScraper(t *testing.T) (s *Scraper, res *rs.Resources, teardown func()) {
172 model, srv := createSim(t)
173 teardown = func() { model.Remove(); srv.Close() }
174
175 c := newClient(t, srv.URL)
176 d := discover.New(c)
177 res, err := d.Discover()
178 require.NoError(t, err)
179
180 return New(c), res, teardown
181 }
182
183 func newClient(t *testing.T, vCenterURL *url.URL) *client.Client {
184 c, err := client.New(client.Config{
185 URL: vCenterURL.String(),
186 User: "admin",
187 Password: "password",
188 Timeout: time.Second * 3,
189 TLSConfig: tlscfg.TLSConfig{InsecureSkipVerify: true},
190 })
191 require.NoError(t, err)
192 return c
193 }
194
195 func createSim(t *testing.T) (*simulator.Model, *simulator.Server) {
196 model := simulator.VPX()
197 err := model.Create()
198 require.NoError(t, err)
199 model.Service.TLS = new(tls.Config)
200 return model, model.Service.NewServer()
201 }
202
203 type mockClient struct {
204 version string
205 perfErr error
206 }
207
208 func (c mockClient) Version() string { return c.version }
209
210 func (c mockClient) PerformanceMetrics([]types.PerfQuerySpec) ([]performance.EntityMetric, error) {
211 return nil, c.perfErr
212 }
213
214 func (c mockClient) VSANPerfMetrics(types.ManagedObjectReference, []vsantypes.VsanPerfQuerySpec) ([]vsantypes.VsanPerfEntityMetricCSV, error) {
215 return nil, nil
216 }
217
218 func (c mockClient) VSANSpaceUsage(types.ManagedObjectReference) (*vsantypes.VsanSpaceUsage, error) {
219 return nil, nil
220 }
221
222 func (c mockClient) VSANHealth(types.ManagedObjectReference) (string, error) {
223 return "", nil
224 }