VictoriaMetrics/lib/promscrape/discovery/vultr/instance_test.go
Zhu Jiekun 10063e98a6
feature: [vmagent] Add service discovery support for Vultr (#6068)
### Describe Your Changes
related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6041

#### Added
- Added service discovery support for Vultr.

#### Docs
- `CHANGELOG.md`, `sd_configs.md`, `vmagent.md` are updated.

#### Note
- Useful links:
- Vultr API:
https://www.vultr.com/api/#tag/instances/operation/list-instances
    - Vultr client SDK: https://github.com/vultr/govultr
- Prometheus SD:
https://github.com/prometheus/prometheus/tree/main/discovery/vultr

---
### Checklist

The following checks are mandatory:

- [X] I have read the [Contributing
Guidelines](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/CONTRIBUTING.md)
- [x] All commits are signed and include `Signed-off-by` line. Use `git
commit -s` to include `Signed-off-by` your commits. See this
[doc](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) about
how to sign your commits.
- [x] Tests are passing locally. Use `make test` to run all tests
locally.
- [x] Linting is passing locally. Use `make check-all` to run all
linters locally.

Further checks are optional for External Contributions:

- [X] Include a link to the GitHub issue in the commit message, if issue
exists.
- [x] Mention the change in the
[Changelog](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/docs/CHANGELOG.md).
Explain what has changed and why. If there is a related issue or
documentation change - link them as well.

  Tips for writing a good changelog message::

* Write a human-readable changelog message that describes the problem
and solution.
* Include a link to the issue or pull request in your changelog message.
* Use specific language identifying the fix, such as an error message,
metric name, or flag name.
* Provide a link to the relevant documentation for any new features you
add or modify.

- [ ] After your pull request is merged, please add a message to the
issue with instructions for how to test the fix or try the feature you
added. Here is an
[example](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4048#issuecomment-1546453726)
- [x] Do not close the original issue before the change is released.
Please note, in some cases Github can automatically close the issue once
PR is merged. Re-open the issue in such case.
- [x] If the change somehow affects public interfaces (a new flag was
added or updated, or some behavior has changed) - add the corresponding
change to documentation.

Signed-off-by: Jiekun <jiekun.dev@gmail.com>
(cherry picked from commit 17e3d019d2)
2024-05-10 14:28:51 +02:00

302 lines
7.9 KiB
Go

package vultr
import (
"errors"
"reflect"
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
)
// TestGetInstances runs general test cases for GetInstances
func TestGetInstances(t *testing.T) {
testCases := []struct {
name string
apiResponse string
apiError bool
expectError bool
expectResponse []Instance
}{
{
name: "success response",
apiResponse: mockListInstanceSuccessResp,
apiError: false,
expectError: false,
expectResponse: expectSuccessInstances,
},
{
name: "failed response",
apiResponse: mockListInstanceFailedResp,
apiError: true,
expectError: true,
expectResponse: nil,
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
// Prepare a mock Vultr server.
mockServer := newMockVultrServer(func() ([]byte, error) {
var e error
if tt.apiError {
e = errors.New("mock error")
}
return []byte(tt.apiResponse), e
})
// Prepare a discovery HTTP client who calls mock server.
client, _ := discoveryutils.NewClient(mockServer.URL, nil, nil, nil, &promauth.HTTPClientConfig{})
cfg := &apiConfig{
c: client,
}
// execute `getInstances`
instances, err := getInstances(cfg)
// evaluate test result
if tt.expectError != (err != nil) {
t.Errorf("getInstances expect (error != nil): %t, got error: %v", tt.expectError, err)
}
if !reflect.DeepEqual(tt.expectResponse, instances) {
t.Errorf("getInstances expect result: %v, got: %v", tt.expectResponse, instances)
}
})
}
}
// TestGetInstancesPaging run test cases for response with multiple pages.
func TestGetInstancesPaging(t *testing.T) {
// Prepare a mock Vultr server.
// requestCount control the mock response for different page request.
requestCount := 0
mockServer := newMockVultrServer(func() ([]byte, error) {
// for the 1st request, response with `next` cursor
if requestCount == 0 {
requestCount++
return []byte(mockListInstanceSuccessPage0Resp), nil
}
// for the 2nd+ request, response with `prev` cursor and empty `next`.
return []byte(mockListInstanceSuccessPage1Resp), nil
})
// Prepare a discovery HTTP client who calls mock server.
client, _ := discoveryutils.NewClient(mockServer.URL, nil, nil, nil, &promauth.HTTPClientConfig{})
cfg := &apiConfig{
c: client,
}
// execute `getInstances`
instances, err := getInstances(cfg)
// evaluate test result
if err != nil {
t.Errorf("getInstances expect error: %v, got error: %v", nil, err)
}
if !reflect.DeepEqual(expectSuccessPagingInstances, instances) {
t.Errorf("getInstances expect result: %v, got: %v", expectSuccessPagingInstances, instances)
}
}
// ------------ Test dataset ------------
var (
// mockListInstanceSuccessResp is crawled from a real-world response of ListInstance API
// with sensitive info removed/modified.
mockListInstanceSuccessResp = `{
"instances": [{
"id": "fake-id-07f7-4b68-88ac-fake-id",
"os": "Ubuntu 22.04 x64",
"ram": 1024,
"disk": 25,
"main_ip": "64.176.84.27",
"vcpu_count": 1,
"region": "sgp",
"plan": "vc2-1c-1gb",
"date_created": "2024-04-05T05:41:28+00:00",
"status": "active",
"allowed_bandwidth": 1,
"netmask_v4": "255.255.254.0",
"gateway_v4": "64.176.63.2",
"power_status": "running",
"server_status": "installingbooting",
"v6_network": "2002:18f0:4100:263a::",
"v6_main_ip": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
"v6_network_size": 64,
"label": "vultr-sd",
"internal_ip": "",
"kvm": "https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=secret_data_string",
"hostname": "vultr-sd",
"tag": "",
"tags": [],
"os_id": 1743,
"app_id": 0,
"image_id": "",
"firewall_group_id": "",
"features": ["ipv6"],
"user_scheme": "root"
}],
"meta": {
"total": 1,
"links": {
"next": "",
"prev": ""
}
}
}`
expectSuccessInstances = []Instance{
{
ID: "fake-id-07f7-4b68-88ac-fake-id",
Os: "Ubuntu 22.04 x64",
RAM: 1024,
Disk: 25,
MainIP: "64.176.84.27",
VCPUCount: 1,
Region: "sgp",
Plan: "vc2-1c-1gb",
AllowedBandwidth: 1,
ServerStatus: "installingbooting",
V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
Label: "vultr-sd",
InternalIP: "",
Hostname: "vultr-sd",
Tags: []string{},
OsID: 1743,
Features: []string{"ipv6"},
},
}
)
var (
mockListInstanceFailedResp = `{"error":"Invalid API token.","status":401}`
)
var (
// mockListInstanceSuccessPage0Resp contains `next` cursor
mockListInstanceSuccessPage0Resp = `{
"instances": [{
"id": "fake-id-07f7-4b68-88ac-fake-id",
"os": "Ubuntu 22.04 x64",
"ram": 1024,
"disk": 25,
"main_ip": "64.176.84.27",
"vcpu_count": 1,
"region": "sgp",
"plan": "vc2-1c-1gb",
"date_created": "2024-04-05T05:41:28+00:00",
"status": "active",
"allowed_bandwidth": 1,
"netmask_v4": "255.255.254.0",
"gateway_v4": "64.176.63.2",
"power_status": "running",
"server_status": "installingbooting",
"v6_network": "2002:18f0:4100:263a::",
"v6_main_ip": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
"v6_network_size": 64,
"label": "vultr-sd",
"internal_ip": "",
"kvm": "https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=secret_data_string",
"hostname": "vultr-sd",
"tag": "",
"tags": [],
"os_id": 1743,
"app_id": 0,
"image_id": "",
"firewall_group_id": "",
"features": ["ipv6"],
"user_scheme": "root"
}],
"meta": {
"total": 2,
"links": {
"next": "fake-cursor-string",
"prev": ""
}
}
}`
// mockListInstanceSuccessPage1Resp contains `prev` cursor
mockListInstanceSuccessPage1Resp = `{
"instances": [{
"id": "fake-id-07f7-4b68-88ac-fake-id",
"os": "Ubuntu 22.04 x64",
"ram": 1024,
"disk": 25,
"main_ip": "64.176.84.27",
"vcpu_count": 1,
"region": "sgp",
"plan": "vc2-1c-1gb",
"date_created": "2024-04-05T05:41:28+00:00",
"status": "active",
"allowed_bandwidth": 1,
"netmask_v4": "255.255.254.0",
"gateway_v4": "64.176.63.2",
"power_status": "running",
"server_status": "installingbooting",
"v6_network": "2002:18f0:4100:263a::",
"v6_main_ip": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
"v6_network_size": 64,
"label": "vultr-sd",
"internal_ip": "",
"kvm": "https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=secret_data_string",
"hostname": "vultr-sd",
"tag": "",
"tags": [],
"os_id": 1743,
"app_id": 0,
"image_id": "",
"firewall_group_id": "",
"features": ["ipv6"],
"user_scheme": "root"
}],
"meta": {
"total": 2,
"links": {
"next": "",
"prev": "fake-cursor-string"
}
}
}`
expectSuccessPagingInstances = []Instance{
{
ID: "fake-id-07f7-4b68-88ac-fake-id",
Os: "Ubuntu 22.04 x64",
RAM: 1024,
Disk: 25,
MainIP: "64.176.84.27",
VCPUCount: 1,
Region: "sgp",
Plan: "vc2-1c-1gb",
AllowedBandwidth: 1,
ServerStatus: "installingbooting",
V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
Label: "vultr-sd",
InternalIP: "",
Hostname: "vultr-sd",
Tags: []string{},
OsID: 1743,
Features: []string{"ipv6"},
},
{
ID: "fake-id-07f7-4b68-88ac-fake-id",
Os: "Ubuntu 22.04 x64",
RAM: 1024,
Disk: 25,
MainIP: "64.176.84.27",
VCPUCount: 1,
Region: "sgp",
Plan: "vc2-1c-1gb",
AllowedBandwidth: 1,
ServerStatus: "installingbooting",
V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
Label: "vultr-sd",
InternalIP: "",
Hostname: "vultr-sd",
Tags: []string{},
OsID: 1743,
Features: []string{"ipv6"},
},
}
)