mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib: consistently use f-tests instead of table-driven tests
This makes easier to read and debug these tests. This also reduces test lines count by 15% from 3K to 2.5K See https://itnext.io/f-tests-as-a-replacement-for-table-driven-tests-in-go-8814a8b19e9e While at it, consistently use t.Fatal* instead of t.Error*, since t.Error* usually leads to more complicated and fragile tests, while it doesn't bring any practical benefits over t.Fatal*.
This commit is contained in:
parent
662e026279
commit
a9525da8a4
35 changed files with 1795 additions and 2272 deletions
|
@ -135,9 +135,13 @@ func TestAuthKeyMetrics(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHandlerWrapper(t *testing.T) {
|
func TestHandlerWrapper(t *testing.T) {
|
||||||
*headerHSTS = "foo"
|
const hstsHeader = "foo"
|
||||||
*headerFrameOptions = "bar"
|
const frameOptionsHeader = "bar"
|
||||||
*headerCSP = "baz"
|
const cspHeader = "baz"
|
||||||
|
|
||||||
|
*headerHSTS = hstsHeader
|
||||||
|
*headerFrameOptions = frameOptionsHeader
|
||||||
|
*headerCSP = cspHeader
|
||||||
defer func() {
|
defer func() {
|
||||||
*headerHSTS = ""
|
*headerHSTS = ""
|
||||||
*headerFrameOptions = ""
|
*headerFrameOptions = ""
|
||||||
|
@ -152,13 +156,14 @@ func TestHandlerWrapper(t *testing.T) {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
if w.Header().Get("Strict-Transport-Security") != "foo" {
|
h := w.Header()
|
||||||
t.Errorf("HSTS header not set")
|
if got := h.Get("Strict-Transport-Security"); got != hstsHeader {
|
||||||
|
t.Fatalf("unexpected HSTS header; got %q; want %q", got, hstsHeader)
|
||||||
}
|
}
|
||||||
if w.Header().Get("X-Frame-Options") != "bar" {
|
if got := h.Get("X-Frame-Options"); got != frameOptionsHeader {
|
||||||
t.Errorf("X-Frame-Options header not set")
|
t.Fatalf("unexpected X-Frame-Options header; got %q; want %q", got, frameOptionsHeader)
|
||||||
}
|
}
|
||||||
if w.Header().Get("Content-Security-Policy") != "baz" {
|
if got := h.Get("Content-Security-Policy"); got != cspHeader {
|
||||||
t.Errorf("CSP header not set")
|
t.Fatalf("unexpected CSP header; got %q; want %q", got, cspHeader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,28 +9,27 @@ func TestTLSConfig(t *testing.T) {
|
||||||
insecureSkipVerify = true
|
insecureSkipVerify = true
|
||||||
tlsCfg, err := TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
tlsCfg, err := TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error %s", err)
|
t.Fatalf("unexpected error %s", err)
|
||||||
}
|
}
|
||||||
if tlsCfg == nil {
|
if tlsCfg == nil {
|
||||||
t.Errorf("expected tlsConfig to be set, got nil")
|
t.Fatalf("expected tlsConfig to be set, got nil")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if tlsCfg.ServerName != serverName {
|
if tlsCfg.ServerName != serverName {
|
||||||
t.Errorf("unexpected ServerName, want %s, got %s", serverName, tlsCfg.ServerName)
|
t.Fatalf("unexpected ServerName, want %s, got %s", serverName, tlsCfg.ServerName)
|
||||||
}
|
}
|
||||||
if tlsCfg.InsecureSkipVerify != insecureSkipVerify {
|
if tlsCfg.InsecureSkipVerify != insecureSkipVerify {
|
||||||
t.Errorf("unexpected InsecureSkipVerify, want %v, got %v", insecureSkipVerify, tlsCfg.InsecureSkipVerify)
|
t.Fatalf("unexpected InsecureSkipVerify, want %v, got %v", insecureSkipVerify, tlsCfg.InsecureSkipVerify)
|
||||||
}
|
}
|
||||||
certFile = "/path/to/nonexisting/cert/file"
|
certFile = "/path/to/nonexisting/cert/file"
|
||||||
_, err = TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
_, err = TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("expected keypair error, got nil")
|
t.Fatalf("expected keypair error, got nil")
|
||||||
}
|
}
|
||||||
certFile = ""
|
certFile = ""
|
||||||
CAFile = "/path/to/nonexisting/cert/file"
|
CAFile = "/path/to/nonexisting/cert/file"
|
||||||
_, err = TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
_, err = TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("expected read error, got nil")
|
t.Fatalf("expected read error, got nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,14 +39,14 @@ func TestTransport(t *testing.T) {
|
||||||
URL := "http://victoriametrics.com"
|
URL := "http://victoriametrics.com"
|
||||||
_, err := Transport(URL, certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
_, err := Transport(URL, certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error %s", err)
|
t.Fatalf("unexpected error %s", err)
|
||||||
}
|
}
|
||||||
URL = "https://victoriametrics.com"
|
URL = "https://victoriametrics.com"
|
||||||
tr, err := Transport(URL, certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
tr, err := Transport(URL, certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error %s", err)
|
t.Fatalf("unexpected error %s", err)
|
||||||
}
|
}
|
||||||
if tr.TLSClientConfig == nil {
|
if tr.TLSClientConfig == nil {
|
||||||
t.Errorf("expected TLSClientConfig to be set, got nil")
|
t.Fatalf("expected TLSClientConfig to be set, got nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,8 +129,7 @@ func TestParseTenantID(t *testing.T) {
|
||||||
|
|
||||||
got, err := ParseTenantID(tenant)
|
got, err := ParseTenantID(tenant)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %s", err)
|
t.Fatalf("unexpected error: %s", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if got.String() != expected.String() {
|
if got.String() != expected.String() {
|
||||||
|
|
|
@ -5,20 +5,21 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseAPIResponse(t *testing.T) {
|
func TestParseAPIResponse(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, responseExpected *listDropletResponse) {
|
||||||
data []byte
|
t.Helper()
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want *listDropletResponse
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
|
|
||||||
{
|
response, err := parseAPIResponse([]byte(data))
|
||||||
name: "simple parse",
|
if err != nil {
|
||||||
args: args{data: []byte(`{
|
t.Fatalf("unexpected parseAPIResponse() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(response, responseExpected) {
|
||||||
|
t.Fatalf("unexpected response\ngot\n%v\nwant\n%v", response, responseExpected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data := `
|
||||||
|
{
|
||||||
"droplets": [
|
"droplets": [
|
||||||
{
|
{
|
||||||
"id": 3164444,
|
"id": 3164444,
|
||||||
|
@ -88,88 +89,70 @@ func Test_parseAPIResponse(t *testing.T) {
|
||||||
"next": "https://api.digitalocean.com/v2/droplets?page=2&per_page=1"
|
"next": "https://api.digitalocean.com/v2/droplets?page=2&per_page=1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`)},
|
}`
|
||||||
want: &listDropletResponse{
|
|
||||||
Droplets: []droplet{
|
responseExpected := &listDropletResponse{
|
||||||
{
|
Droplets: []droplet{
|
||||||
Image: struct {
|
{
|
||||||
Name string `json:"name"`
|
Image: dropletImage{
|
||||||
Slug string `json:"slug"`
|
Name: "14.04 x64",
|
||||||
}(struct {
|
Slug: "ubuntu-16-04-x64",
|
||||||
Name string
|
},
|
||||||
Slug string
|
Region: dropletRegion{
|
||||||
}{Name: "14.04 x64", Slug: "ubuntu-16-04-x64"}),
|
Slug: "nyc3",
|
||||||
Region: struct {
|
},
|
||||||
Slug string `json:"slug"`
|
Networks: networks{
|
||||||
}(struct{ Slug string }{Slug: "nyc3"}),
|
V6: []network{
|
||||||
Networks: networks{
|
{
|
||||||
V6: []network{
|
IPAddress: "2604:A880:0800:0010:0000:0000:02DD:4001",
|
||||||
{
|
Type: "public",
|
||||||
IPAddress: "2604:A880:0800:0010:0000:0000:02DD:4001",
|
},
|
||||||
Type: "public",
|
},
|
||||||
},
|
V4: []network{
|
||||||
},
|
{
|
||||||
V4: []network{
|
IPAddress: "104.236.32.182",
|
||||||
{
|
Type: "public",
|
||||||
IPAddress: "104.236.32.182",
|
|
||||||
Type: "public",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
SizeSlug: "s-1vcpu-1gb",
|
|
||||||
Features: []string{"backups", "ipv6", "virtio"},
|
|
||||||
Tags: []string{"tag1", "tag2"},
|
|
||||||
Status: "active",
|
|
||||||
Name: "example.com",
|
|
||||||
ID: 3164444,
|
|
||||||
VpcUUID: "f9b0769c-e118-42fb-a0c4-fed15ef69662",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Links: links{
|
SizeSlug: "s-1vcpu-1gb",
|
||||||
Pages: struct {
|
Features: []string{"backups", "ipv6", "virtio"},
|
||||||
Last string `json:"last,omitempty"`
|
Tags: []string{"tag1", "tag2"},
|
||||||
Next string `json:"next,omitempty"`
|
Status: "active",
|
||||||
}(struct {
|
Name: "example.com",
|
||||||
Last string
|
ID: 3164444,
|
||||||
Next string
|
VpcUUID: "f9b0769c-e118-42fb-a0c4-fed15ef69662",
|
||||||
}{Last: "https://api.digitalocean.com/v2/droplets?page=3&per_page=1", Next: "https://api.digitalocean.com/v2/droplets?page=2&per_page=1"}),
|
},
|
||||||
},
|
},
|
||||||
|
Links: links{
|
||||||
|
Pages: linksPages{
|
||||||
|
Last: "https://api.digitalocean.com/v2/droplets?page=3&per_page=1",
|
||||||
|
Next: "https://api.digitalocean.com/v2/droplets?page=2&per_page=1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, responseExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseAPIResponse(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseAPIResponse() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseAPIResponse() got = \n%v\n, \nwant \n%v\n", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_getDroplets(t *testing.T) {
|
func TestGetDroplets(t *testing.T) {
|
||||||
type args struct {
|
f := func(getAPIResponse func(string) ([]byte, error), expectedDropletCount int) {
|
||||||
getAPIResponse func(string) ([]byte, error)
|
t.Helper()
|
||||||
|
|
||||||
|
resp, err := getDroplets(getAPIResponse)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("getDroplets() error: %s", err)
|
||||||
|
}
|
||||||
|
if len(resp) != expectedDropletCount {
|
||||||
|
t.Fatalf("unexpected droplets count; got %d; want %d\ndroplets:\n%v", len(resp), expectedDropletCount, resp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
getAPIResponse := func(s string) ([]byte, error) {
|
||||||
args args
|
var resp []byte
|
||||||
wantDropletCount int
|
switch s {
|
||||||
wantErr bool
|
case dropletsAPIPath:
|
||||||
}{
|
// return next
|
||||||
{
|
resp = []byte(`{ "droplets": [
|
||||||
name: "get 4 droples",
|
|
||||||
args: args{
|
|
||||||
func(s string) ([]byte, error) {
|
|
||||||
var resp []byte
|
|
||||||
switch s {
|
|
||||||
case dropletsAPIPath:
|
|
||||||
// return next
|
|
||||||
resp = []byte(`{ "droplets": [
|
|
||||||
{
|
{
|
||||||
"id": 3164444,
|
"id": 3164444,
|
||||||
"name": "example.com",
|
"name": "example.com",
|
||||||
|
@ -267,9 +250,9 @@ func Test_getDroplets(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
default:
|
default:
|
||||||
// return with empty next
|
// return with empty next
|
||||||
resp = []byte(`{ "droplets": [
|
resp = []byte(`{ "droplets": [
|
||||||
{
|
{
|
||||||
"id": 3164444,
|
"id": 3164444,
|
||||||
"name": "example.com",
|
"name": "example.com",
|
||||||
|
@ -326,24 +309,8 @@ func Test_getDroplets(t *testing.T) {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`)
|
}`)
|
||||||
}
|
}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
},
|
|
||||||
},
|
|
||||||
wantDropletCount: 5,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := getDroplets(tt.args.getAPIResponse)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("getDroplets() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(got) != tt.wantDropletCount {
|
|
||||||
t.Fatalf("unexpected droplets count: %d, want: %d, \n droplets: %v\n", len(got), tt.wantDropletCount, got)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
f(getAPIResponse, 5)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,18 +49,22 @@ type droplet struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
|
|
||||||
Features []string `json:"features"`
|
Features []string `json:"features"`
|
||||||
Image struct {
|
Image dropletImage `json:"image"`
|
||||||
Name string `json:"name"`
|
SizeSlug string `json:"size_slug"`
|
||||||
Slug string `json:"slug"`
|
Networks networks `json:"networks"`
|
||||||
} `json:"image"`
|
Region dropletRegion `json:"region"`
|
||||||
SizeSlug string `json:"size_slug"`
|
Tags []string `json:"tags"`
|
||||||
Networks networks `json:"networks"`
|
VpcUUID string `json:"vpc_uuid"`
|
||||||
Region struct {
|
}
|
||||||
Slug string `json:"slug"`
|
|
||||||
} `json:"region"`
|
type dropletImage struct {
|
||||||
Tags []string `json:"tags"`
|
Name string `json:"name"`
|
||||||
VpcUUID string `json:"vpc_uuid"`
|
Slug string `json:"slug"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type dropletRegion struct {
|
||||||
|
Slug string `json:"slug"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *droplet) getIPByNet(netVersion, netType string) string {
|
func (d *droplet) getIPByNet(netVersion, netType string) string {
|
||||||
|
@ -98,10 +102,12 @@ type listDropletResponse struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type links struct {
|
type links struct {
|
||||||
Pages struct {
|
Pages linksPages `json:"pages,omitempty"`
|
||||||
Last string `json:"last,omitempty"`
|
}
|
||||||
Next string `json:"next,omitempty"`
|
|
||||||
} `json:"pages,omitempty"`
|
type linksPages struct {
|
||||||
|
Last string `json:"last,omitempty"`
|
||||||
|
Next string `json:"next,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *listDropletResponse) nextURLPath() (string, error) {
|
func (r *listDropletResponse) nextURLPath() (string, error) {
|
||||||
|
|
|
@ -7,84 +7,68 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_addDropletLabels(t *testing.T) {
|
func TestAddDropletLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(droplets []droplet, labelssExpected []*promutils.Labels) {
|
||||||
droplets []droplet
|
t.Helper()
|
||||||
defaultPort int
|
|
||||||
|
labelss := addDropletLabels(droplets, 9100)
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// base labels add test
|
||||||
args args
|
droplets := []droplet{
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "base labels add test",
|
ID: 15,
|
||||||
args: args{
|
Tags: []string{"private", "test"},
|
||||||
droplets: []droplet{
|
Status: "active",
|
||||||
|
Name: "ubuntu-1",
|
||||||
|
Region: dropletRegion{
|
||||||
|
Slug: "do",
|
||||||
|
},
|
||||||
|
Features: []string{"feature-1", "feature-2"},
|
||||||
|
SizeSlug: "base-1",
|
||||||
|
VpcUUID: "vpc-1",
|
||||||
|
Image: dropletImage{
|
||||||
|
Name: "ubuntu",
|
||||||
|
Slug: "18",
|
||||||
|
},
|
||||||
|
Networks: networks{
|
||||||
|
V4: []network{
|
||||||
{
|
{
|
||||||
ID: 15,
|
Type: "public",
|
||||||
Tags: []string{"private", "test"},
|
IPAddress: "100.100.100.100",
|
||||||
Status: "active",
|
},
|
||||||
Name: "ubuntu-1",
|
{
|
||||||
Region: struct {
|
Type: "private",
|
||||||
Slug string `json:"slug"`
|
IPAddress: "10.10.10.10",
|
||||||
}(struct{ Slug string }{Slug: "do"}),
|
},
|
||||||
Features: []string{"feature-1", "feature-2"},
|
},
|
||||||
SizeSlug: "base-1",
|
V6: []network{
|
||||||
VpcUUID: "vpc-1",
|
{
|
||||||
Image: struct {
|
Type: "public",
|
||||||
Name string `json:"name"`
|
IPAddress: "::1",
|
||||||
Slug string `json:"slug"`
|
|
||||||
}(struct {
|
|
||||||
Name string
|
|
||||||
Slug string
|
|
||||||
}{Name: "ubuntu", Slug: "18"}),
|
|
||||||
Networks: networks{
|
|
||||||
V4: []network{
|
|
||||||
{
|
|
||||||
Type: "public",
|
|
||||||
IPAddress: "100.100.100.100",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: "private",
|
|
||||||
IPAddress: "10.10.10.10",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
V6: []network{
|
|
||||||
{
|
|
||||||
Type: "public",
|
|
||||||
IPAddress: "::1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultPort: 9100,
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "100.100.100.100:9100",
|
|
||||||
"__meta_digitalocean_droplet_id": "15",
|
|
||||||
"__meta_digitalocean_droplet_name": "ubuntu-1",
|
|
||||||
"__meta_digitalocean_features": ",feature-1,feature-2,",
|
|
||||||
"__meta_digitalocean_image": "18",
|
|
||||||
"__meta_digitalocean_image_name": "ubuntu",
|
|
||||||
"__meta_digitalocean_private_ipv4": "10.10.10.10",
|
|
||||||
"__meta_digitalocean_public_ipv4": "100.100.100.100",
|
|
||||||
"__meta_digitalocean_public_ipv6": "::1",
|
|
||||||
"__meta_digitalocean_region": "do",
|
|
||||||
"__meta_digitalocean_size": "base-1",
|
|
||||||
"__meta_digitalocean_status": "active",
|
|
||||||
"__meta_digitalocean_tags": ",private,test,",
|
|
||||||
"__meta_digitalocean_vpc": "vpc-1",
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected := []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addDropletLabels(tt.args.droplets, tt.args.defaultPort)
|
"__address__": "100.100.100.100:9100",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_digitalocean_droplet_id": "15",
|
||||||
})
|
"__meta_digitalocean_droplet_name": "ubuntu-1",
|
||||||
|
"__meta_digitalocean_features": ",feature-1,feature-2,",
|
||||||
|
"__meta_digitalocean_image": "18",
|
||||||
|
"__meta_digitalocean_image_name": "ubuntu",
|
||||||
|
"__meta_digitalocean_private_ipv4": "10.10.10.10",
|
||||||
|
"__meta_digitalocean_public_ipv4": "100.100.100.100",
|
||||||
|
"__meta_digitalocean_public_ipv6": "::1",
|
||||||
|
"__meta_digitalocean_region": "do",
|
||||||
|
"__meta_digitalocean_size": "base-1",
|
||||||
|
"__meta_digitalocean_status": "active",
|
||||||
|
"__meta_digitalocean_tags": ",private,test,",
|
||||||
|
"__meta_digitalocean_vpc": "vpc-1",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
f(droplets, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,24 +11,32 @@ import (
|
||||||
|
|
||||||
// See https://github.com/moby/moby/blob/314759dc2f4745925d8dec6d15acc7761c6e5c92/docs/api/v1.41.yaml#L4024
|
// See https://github.com/moby/moby/blob/314759dc2f4745925d8dec6d15acc7761c6e5c92/docs/api/v1.41.yaml#L4024
|
||||||
type container struct {
|
type container struct {
|
||||||
ID string
|
ID string
|
||||||
Names []string
|
Names []string
|
||||||
Labels map[string]string
|
Labels map[string]string
|
||||||
Ports []struct {
|
Ports []containerPort
|
||||||
IP string
|
HostConfig containerHostConfig
|
||||||
PrivatePort int
|
NetworkSettings containerNetworkSettings
|
||||||
PublicPort int
|
}
|
||||||
Type string
|
|
||||||
}
|
type containerPort struct {
|
||||||
HostConfig struct {
|
IP string
|
||||||
NetworkMode string
|
PrivatePort int
|
||||||
}
|
PublicPort int
|
||||||
NetworkSettings struct {
|
Type string
|
||||||
Networks map[string]struct {
|
}
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
type containerHostConfig struct {
|
||||||
}
|
NetworkMode string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type containerNetworkSettings struct {
|
||||||
|
Networks map[string]containerNetwork
|
||||||
|
}
|
||||||
|
|
||||||
|
type containerNetwork struct {
|
||||||
|
IPAddress string
|
||||||
|
NetworkID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
func getContainersLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
||||||
|
|
|
@ -8,20 +8,20 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseContainers(t *testing.T) {
|
func TePParseContainers(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, resultExpected []container) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
result, err := parseContainers([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseContainers() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%v\nwant\n%v", result, resultExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
data := `[
|
||||||
args args
|
|
||||||
want []container
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse two containers",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`[
|
|
||||||
{
|
{
|
||||||
"Id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
"Id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
"Names": [
|
"Names": [
|
||||||
|
@ -116,115 +116,83 @@ func Test_parseContainers(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]`),
|
]`
|
||||||
|
resultExpected := []container{
|
||||||
|
{
|
||||||
|
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
|
Names: []string{"/crow-server"},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
||||||
|
"com.docker.compose.container-number": "1",
|
||||||
|
"com.docker.compose.oneoff": "False",
|
||||||
|
"com.docker.compose.project": "crowserver",
|
||||||
|
"com.docker.compose.service": "crow-server",
|
||||||
|
"com.docker.compose.version": "1.11.2",
|
||||||
},
|
},
|
||||||
want: []container{
|
Ports: []containerPort{
|
||||||
{
|
{
|
||||||
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
IP: "0.0.0.0",
|
||||||
Names: []string{"/crow-server"},
|
PrivatePort: 8080,
|
||||||
Labels: map[string]string{
|
PublicPort: 18081,
|
||||||
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
Type: "tcp",
|
||||||
"com.docker.compose.container-number": "1",
|
},
|
||||||
"com.docker.compose.oneoff": "False",
|
},
|
||||||
"com.docker.compose.project": "crowserver",
|
HostConfig: containerHostConfig{
|
||||||
"com.docker.compose.service": "crow-server",
|
NetworkMode: "bridge",
|
||||||
"com.docker.compose.version": "1.11.2",
|
},
|
||||||
},
|
NetworkSettings: containerNetworkSettings{
|
||||||
Ports: []struct {
|
Networks: map[string]containerNetwork{
|
||||||
IP string
|
"bridge": {
|
||||||
PrivatePort int
|
IPAddress: "172.17.0.2",
|
||||||
PublicPort int
|
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
Type string
|
|
||||||
}{{
|
|
||||||
IP: "0.0.0.0",
|
|
||||||
PrivatePort: 8080,
|
|
||||||
PublicPort: 18081,
|
|
||||||
Type: "tcp",
|
|
||||||
}},
|
|
||||||
HostConfig: struct {
|
|
||||||
NetworkMode string
|
|
||||||
}{
|
|
||||||
NetworkMode: "bridge",
|
|
||||||
},
|
|
||||||
NetworkSettings: struct {
|
|
||||||
Networks map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Networks: map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}{
|
|
||||||
"bridge": {
|
|
||||||
IPAddress: "172.17.0.2",
|
|
||||||
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "0e0f72a6eb7d9fb443f0426a66f7b8dd7d3283ab7e3a308b2bed584ac03a33dc",
|
||||||
|
Names: []string{"/crow-web"},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"com.docker.compose.config-hash": "d99ebd0fde8512366c2d78c367e95ddc74528bb60b7cf0c991c9f4835981e00e",
|
||||||
|
"com.docker.compose.container-number": "1",
|
||||||
|
"com.docker.compose.oneoff": "False",
|
||||||
|
"com.docker.compose.project": "crowweb",
|
||||||
|
"com.docker.compose.service": "crow-web",
|
||||||
|
"com.docker.compose.version": "1.11.2",
|
||||||
|
},
|
||||||
|
Ports: []containerPort{
|
||||||
{
|
{
|
||||||
ID: "0e0f72a6eb7d9fb443f0426a66f7b8dd7d3283ab7e3a308b2bed584ac03a33dc",
|
IP: "0.0.0.0",
|
||||||
Names: []string{"/crow-web"},
|
PrivatePort: 8080,
|
||||||
Labels: map[string]string{
|
PublicPort: 18082,
|
||||||
"com.docker.compose.config-hash": "d99ebd0fde8512366c2d78c367e95ddc74528bb60b7cf0c991c9f4835981e00e",
|
Type: "tcp",
|
||||||
"com.docker.compose.container-number": "1",
|
},
|
||||||
"com.docker.compose.oneoff": "False",
|
},
|
||||||
"com.docker.compose.project": "crowweb",
|
HostConfig: containerHostConfig{
|
||||||
"com.docker.compose.service": "crow-web",
|
NetworkMode: "bridge",
|
||||||
"com.docker.compose.version": "1.11.2",
|
},
|
||||||
},
|
NetworkSettings: containerNetworkSettings{
|
||||||
Ports: []struct {
|
Networks: map[string]containerNetwork{
|
||||||
IP string
|
"bridge": {
|
||||||
PrivatePort int
|
IPAddress: "172.17.0.3",
|
||||||
PublicPort int
|
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
Type string
|
|
||||||
}{{
|
|
||||||
IP: "0.0.0.0",
|
|
||||||
PrivatePort: 8080,
|
|
||||||
PublicPort: 18082,
|
|
||||||
Type: "tcp",
|
|
||||||
}},
|
|
||||||
HostConfig: struct {
|
|
||||||
NetworkMode string
|
|
||||||
}{
|
|
||||||
NetworkMode: "bridge",
|
|
||||||
},
|
|
||||||
NetworkSettings: struct {
|
|
||||||
Networks map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Networks: map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}{
|
|
||||||
"bridge": {
|
|
||||||
IPAddress: "172.17.0.3",
|
|
||||||
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
f(data, resultExpected)
|
||||||
got, err := parseContainers(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseContainers() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseNetworks() \ngot %v, \nwant %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_addContainerLabels(t *testing.T) {
|
func TestAddContainerLabels(t *testing.T) {
|
||||||
|
f := func(c container, networkLabels map[string]*promutils.Labels, labelssExpected []*promutils.Labels) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
labelss := addContainersLabels([]container{c}, networkLabels, 8012, "foobar")
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
|
}
|
||||||
|
|
||||||
data := []byte(`[
|
data := []byte(`[
|
||||||
{
|
{
|
||||||
"Name": "host",
|
"Name": "host",
|
||||||
|
@ -314,204 +282,152 @@ func Test_addContainerLabels(t *testing.T) {
|
||||||
}
|
}
|
||||||
networkLabels := getNetworkLabelsByNetworkID(networks)
|
networkLabels := getNetworkLabelsByNetworkID(networks)
|
||||||
|
|
||||||
tests := []struct {
|
// NetworkMode != host
|
||||||
name string
|
c := container{
|
||||||
c container
|
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
want []*promutils.Labels
|
Names: []string{"/crow-server"},
|
||||||
wantErr bool
|
Labels: map[string]string{
|
||||||
}{
|
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
||||||
{
|
"com.docker.compose.container-number": "1",
|
||||||
name: "NetworkMode!=host",
|
"com.docker.compose.oneoff": "False",
|
||||||
c: container{
|
"com.docker.compose.project": "crowserver",
|
||||||
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
"com.docker.compose.service": "crow-server",
|
||||||
Names: []string{"/crow-server"},
|
"com.docker.compose.version": "1.11.2",
|
||||||
Labels: map[string]string{
|
|
||||||
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
|
||||||
"com.docker.compose.container-number": "1",
|
|
||||||
"com.docker.compose.oneoff": "False",
|
|
||||||
"com.docker.compose.project": "crowserver",
|
|
||||||
"com.docker.compose.service": "crow-server",
|
|
||||||
"com.docker.compose.version": "1.11.2",
|
|
||||||
},
|
|
||||||
HostConfig: struct {
|
|
||||||
NetworkMode string
|
|
||||||
}{
|
|
||||||
NetworkMode: "bridge",
|
|
||||||
},
|
|
||||||
NetworkSettings: struct {
|
|
||||||
Networks map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Networks: map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}{
|
|
||||||
"host": {
|
|
||||||
IPAddress: "172.17.0.2",
|
|
||||||
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "172.17.0.2:8012",
|
|
||||||
"__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_container_number": "1",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_oneoff": "False",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_project": "crowserver",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_service": "crow-server",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_version": "1.11.2",
|
|
||||||
"__meta_docker_container_name": "/crow-server",
|
|
||||||
"__meta_docker_container_network_mode": "bridge",
|
|
||||||
"__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
"__meta_docker_network_ingress": "false",
|
|
||||||
"__meta_docker_network_internal": "false",
|
|
||||||
"__meta_docker_network_ip": "172.17.0.2",
|
|
||||||
"__meta_docker_network_name": "bridge",
|
|
||||||
"__meta_docker_network_scope": "local",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
HostConfig: containerHostConfig{
|
||||||
name: "NetworkMode=host",
|
NetworkMode: "bridge",
|
||||||
c: container{
|
|
||||||
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
|
||||||
Names: []string{"/crow-server"},
|
|
||||||
Labels: map[string]string{
|
|
||||||
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
|
||||||
"com.docker.compose.container-number": "1",
|
|
||||||
"com.docker.compose.oneoff": "False",
|
|
||||||
"com.docker.compose.project": "crowserver",
|
|
||||||
"com.docker.compose.service": "crow-server",
|
|
||||||
"com.docker.compose.version": "1.11.2",
|
|
||||||
},
|
|
||||||
HostConfig: struct {
|
|
||||||
NetworkMode string
|
|
||||||
}{
|
|
||||||
NetworkMode: "host",
|
|
||||||
},
|
|
||||||
NetworkSettings: struct {
|
|
||||||
Networks map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Networks: map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}{
|
|
||||||
"host": {
|
|
||||||
IPAddress: "172.17.0.2",
|
|
||||||
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "foobar",
|
|
||||||
"__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_container_number": "1",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_oneoff": "False",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_project": "crowserver",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_service": "crow-server",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_version": "1.11.2",
|
|
||||||
"__meta_docker_container_name": "/crow-server",
|
|
||||||
"__meta_docker_container_network_mode": "host",
|
|
||||||
"__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
"__meta_docker_network_ingress": "false",
|
|
||||||
"__meta_docker_network_internal": "false",
|
|
||||||
"__meta_docker_network_ip": "172.17.0.2",
|
|
||||||
"__meta_docker_network_name": "bridge",
|
|
||||||
"__meta_docker_network_scope": "local",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
NetworkSettings: containerNetworkSettings{
|
||||||
name: "get labels from a container",
|
Networks: map[string]containerNetwork{
|
||||||
c: container{
|
"host": {
|
||||||
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
IPAddress: "172.17.0.2",
|
||||||
Names: []string{"/crow-server"},
|
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
Labels: map[string]string{
|
|
||||||
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
|
||||||
"com.docker.compose.container-number": "1",
|
|
||||||
"com.docker.compose.oneoff": "False",
|
|
||||||
"com.docker.compose.project": "crowserver",
|
|
||||||
"com.docker.compose.service": "crow-server",
|
|
||||||
"com.docker.compose.version": "1.11.2",
|
|
||||||
},
|
},
|
||||||
Ports: []struct {
|
|
||||||
IP string
|
|
||||||
PrivatePort int
|
|
||||||
PublicPort int
|
|
||||||
Type string
|
|
||||||
}{{
|
|
||||||
IP: "0.0.0.0",
|
|
||||||
PrivatePort: 8080,
|
|
||||||
PublicPort: 18081,
|
|
||||||
Type: "tcp",
|
|
||||||
}},
|
|
||||||
HostConfig: struct {
|
|
||||||
NetworkMode string
|
|
||||||
}{
|
|
||||||
NetworkMode: "bridge",
|
|
||||||
},
|
|
||||||
NetworkSettings: struct {
|
|
||||||
Networks map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Networks: map[string]struct {
|
|
||||||
IPAddress string
|
|
||||||
NetworkID string
|
|
||||||
}{
|
|
||||||
"bridge": {
|
|
||||||
IPAddress: "172.17.0.2",
|
|
||||||
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "172.17.0.2:8080",
|
|
||||||
"__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_container_number": "1",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_oneoff": "False",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_project": "crowserver",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_service": "crow-server",
|
|
||||||
"__meta_docker_container_label_com_docker_compose_version": "1.11.2",
|
|
||||||
"__meta_docker_container_name": "/crow-server",
|
|
||||||
"__meta_docker_container_network_mode": "bridge",
|
|
||||||
"__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
|
||||||
"__meta_docker_network_ingress": "false",
|
|
||||||
"__meta_docker_network_internal": "false",
|
|
||||||
"__meta_docker_network_ip": "172.17.0.2",
|
|
||||||
"__meta_docker_network_name": "bridge",
|
|
||||||
"__meta_docker_network_scope": "local",
|
|
||||||
"__meta_docker_port_private": "8080",
|
|
||||||
"__meta_docker_port_public": "18081",
|
|
||||||
"__meta_docker_port_public_ip": "0.0.0.0",
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
labelssExpected := []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "172.17.0.2:8012",
|
||||||
|
"__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_container_number": "1",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_oneoff": "False",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_project": "crowserver",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_service": "crow-server",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_version": "1.11.2",
|
||||||
|
"__meta_docker_container_name": "/crow-server",
|
||||||
|
"__meta_docker_container_network_mode": "bridge",
|
||||||
|
"__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
|
"__meta_docker_network_ingress": "false",
|
||||||
|
"__meta_docker_network_internal": "false",
|
||||||
|
"__meta_docker_network_ip": "172.17.0.2",
|
||||||
|
"__meta_docker_network_name": "bridge",
|
||||||
|
"__meta_docker_network_scope": "local",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(c, networkLabels, labelssExpected)
|
||||||
|
|
||||||
for _, tt := range tests {
|
// NetworkMode=host
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
c = container{
|
||||||
labelss := addContainersLabels([]container{tt.c}, networkLabels, 8012, "foobar")
|
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
if (err != nil) != tt.wantErr {
|
Names: []string{"/crow-server"},
|
||||||
t.Errorf("addContainersLabels() error = %v, wantErr %v", err, tt.wantErr)
|
Labels: map[string]string{
|
||||||
return
|
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
||||||
}
|
"com.docker.compose.container-number": "1",
|
||||||
discoveryutils.TestEqualLabelss(t, labelss, tt.want)
|
"com.docker.compose.oneoff": "False",
|
||||||
})
|
"com.docker.compose.project": "crowserver",
|
||||||
|
"com.docker.compose.service": "crow-server",
|
||||||
|
"com.docker.compose.version": "1.11.2",
|
||||||
|
},
|
||||||
|
HostConfig: containerHostConfig{
|
||||||
|
NetworkMode: "host",
|
||||||
|
},
|
||||||
|
NetworkSettings: containerNetworkSettings{
|
||||||
|
Networks: map[string]containerNetwork{
|
||||||
|
"host": {
|
||||||
|
IPAddress: "172.17.0.2",
|
||||||
|
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
labelssExpected = []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "foobar",
|
||||||
|
"__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_container_number": "1",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_oneoff": "False",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_project": "crowserver",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_service": "crow-server",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_version": "1.11.2",
|
||||||
|
"__meta_docker_container_name": "/crow-server",
|
||||||
|
"__meta_docker_container_network_mode": "host",
|
||||||
|
"__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
|
"__meta_docker_network_ingress": "false",
|
||||||
|
"__meta_docker_network_internal": "false",
|
||||||
|
"__meta_docker_network_ip": "172.17.0.2",
|
||||||
|
"__meta_docker_network_name": "bridge",
|
||||||
|
"__meta_docker_network_scope": "local",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(c, networkLabels, labelssExpected)
|
||||||
|
|
||||||
|
// get labels from a container
|
||||||
|
c = container{
|
||||||
|
ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
|
Names: []string{"/crow-server"},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
||||||
|
"com.docker.compose.container-number": "1",
|
||||||
|
"com.docker.compose.oneoff": "False",
|
||||||
|
"com.docker.compose.project": "crowserver",
|
||||||
|
"com.docker.compose.service": "crow-server",
|
||||||
|
"com.docker.compose.version": "1.11.2",
|
||||||
|
},
|
||||||
|
Ports: []containerPort{
|
||||||
|
{
|
||||||
|
IP: "0.0.0.0",
|
||||||
|
PrivatePort: 8080,
|
||||||
|
PublicPort: 18081,
|
||||||
|
Type: "tcp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HostConfig: containerHostConfig{
|
||||||
|
NetworkMode: "bridge",
|
||||||
|
},
|
||||||
|
NetworkSettings: containerNetworkSettings{
|
||||||
|
Networks: map[string]containerNetwork{
|
||||||
|
"bridge": {
|
||||||
|
IPAddress: "172.17.0.2",
|
||||||
|
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
labelssExpected = []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "172.17.0.2:8080",
|
||||||
|
"__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_container_number": "1",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_oneoff": "False",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_project": "crowserver",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_service": "crow-server",
|
||||||
|
"__meta_docker_container_label_com_docker_compose_version": "1.11.2",
|
||||||
|
"__meta_docker_container_name": "/crow-server",
|
||||||
|
"__meta_docker_container_network_mode": "bridge",
|
||||||
|
"__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||||
|
"__meta_docker_network_ingress": "false",
|
||||||
|
"__meta_docker_network_internal": "false",
|
||||||
|
"__meta_docker_network_ip": "172.17.0.2",
|
||||||
|
"__meta_docker_network_name": "bridge",
|
||||||
|
"__meta_docker_network_scope": "local",
|
||||||
|
"__meta_docker_port_private": "8080",
|
||||||
|
"__meta_docker_port_public": "18081",
|
||||||
|
"__meta_docker_port_public_ip": "0.0.0.0",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(c, networkLabels, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,72 +9,64 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_addNetworkLabels(t *testing.T) {
|
func TestAddNetworkLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(networks []network, labelssExpected []*promutils.Labels) {
|
||||||
networks []network
|
t.Helper()
|
||||||
|
|
||||||
|
networkLabels := getNetworkLabelsByNetworkID(networks)
|
||||||
|
|
||||||
|
var networkIDs []string
|
||||||
|
for networkID := range networkLabels {
|
||||||
|
networkIDs = append(networkIDs, networkID)
|
||||||
|
}
|
||||||
|
sort.Strings(networkIDs)
|
||||||
|
var labelss []*promutils.Labels
|
||||||
|
for _, networkID := range networkIDs {
|
||||||
|
labelss = append(labelss, networkLabels[networkID])
|
||||||
|
}
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// ingress network
|
||||||
args args
|
networks := []network{
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "ingress network",
|
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
args: args{
|
Ingress: true,
|
||||||
networks: []network{
|
Scope: "swarm",
|
||||||
{
|
Name: "ingress",
|
||||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
Labels: map[string]string{
|
||||||
Ingress: true,
|
"key1": "value1",
|
||||||
Scope: "swarm",
|
|
||||||
Name: "ingress",
|
|
||||||
Labels: map[string]string{
|
|
||||||
"key1": "value1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__meta_docker_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
"__meta_docker_network_ingress": "true",
|
|
||||||
"__meta_docker_network_internal": "false",
|
|
||||||
"__meta_docker_network_label_key1": "value1",
|
|
||||||
"__meta_docker_network_name": "ingress",
|
|
||||||
"__meta_docker_network_scope": "swarm",
|
|
||||||
})},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected := []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := getNetworkLabelsByNetworkID(tt.args.networks)
|
"__meta_docker_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
var networkIDs []string
|
"__meta_docker_network_ingress": "true",
|
||||||
for networkID := range got {
|
"__meta_docker_network_internal": "false",
|
||||||
networkIDs = append(networkIDs, networkID)
|
"__meta_docker_network_label_key1": "value1",
|
||||||
}
|
"__meta_docker_network_name": "ingress",
|
||||||
sort.Strings(networkIDs)
|
"__meta_docker_network_scope": "swarm",
|
||||||
var labelss []*promutils.Labels
|
}),
|
||||||
for _, networkID := range networkIDs {
|
|
||||||
labelss = append(labelss, got[networkID])
|
|
||||||
}
|
|
||||||
discoveryutils.TestEqualLabelss(t, labelss, tt.want)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
f(networks, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_parseNetworks(t *testing.T) {
|
func TestParseNetworks(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, resultExpected []network) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
result, err := parseNetworks([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseNetworks() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
|
t.Fatalf("unexpected networks\ngot\n%v\nwant\n%v", result, resultExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// parse two networks
|
||||||
args args
|
data := `[
|
||||||
want []network
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse two networks",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`[
|
|
||||||
{
|
{
|
||||||
"Name": "ingress",
|
"Name": "ingress",
|
||||||
"Id": "qs0hog6ldlei9ct11pr3c77v1",
|
"Id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
@ -132,39 +124,25 @@ func Test_parseNetworks(t *testing.T) {
|
||||||
"key": "value"
|
"key": "value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]`),
|
]`
|
||||||
|
resultExpected := []network{
|
||||||
|
{
|
||||||
|
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
Ingress: true,
|
||||||
|
Scope: "swarm",
|
||||||
|
Name: "ingress",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"key1": "value1",
|
||||||
},
|
},
|
||||||
want: []network{
|
},
|
||||||
{
|
{
|
||||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
||||||
Ingress: true,
|
Scope: "local",
|
||||||
Scope: "swarm",
|
Name: "host",
|
||||||
Name: "ingress",
|
Labels: map[string]string{
|
||||||
Labels: map[string]string{
|
"key": "value",
|
||||||
"key1": "value1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
|
||||||
Scope: "local",
|
|
||||||
Name: "host",
|
|
||||||
Labels: map[string]string{
|
|
||||||
"key": "value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, resultExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseNetworks(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseNetworks() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseNetworks() \ngot %v, \nwant %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,72 +9,64 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_addNetworkLabels(t *testing.T) {
|
func TestAddNetworkLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(networks []network, labelssExpected []*promutils.Labels) {
|
||||||
networks []network
|
t.Helper()
|
||||||
|
|
||||||
|
networkLabels := getNetworkLabelsByNetworkID(networks)
|
||||||
|
|
||||||
|
var networkIDs []string
|
||||||
|
for networkID := range networkLabels {
|
||||||
|
networkIDs = append(networkIDs, networkID)
|
||||||
|
}
|
||||||
|
sort.Strings(networkIDs)
|
||||||
|
var labelss []*promutils.Labels
|
||||||
|
for _, networkID := range networkIDs {
|
||||||
|
labelss = append(labelss, networkLabels[networkID])
|
||||||
|
}
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// ingress network
|
||||||
args args
|
networks := []network{
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "ingress network",
|
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
args: args{
|
Ingress: true,
|
||||||
networks: []network{
|
Scope: "swarm",
|
||||||
{
|
Name: "ingress",
|
||||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
Labels: map[string]string{
|
||||||
Ingress: true,
|
"key1": "value1",
|
||||||
Scope: "swarm",
|
|
||||||
Name: "ingress",
|
|
||||||
Labels: map[string]string{
|
|
||||||
"key1": "value1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
"__meta_dockerswarm_network_ingress": "true",
|
|
||||||
"__meta_dockerswarm_network_internal": "false",
|
|
||||||
"__meta_dockerswarm_network_label_key1": "value1",
|
|
||||||
"__meta_dockerswarm_network_name": "ingress",
|
|
||||||
"__meta_dockerswarm_network_scope": "swarm",
|
|
||||||
})},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected := []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := getNetworkLabelsByNetworkID(tt.args.networks)
|
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
var networkIDs []string
|
"__meta_dockerswarm_network_ingress": "true",
|
||||||
for networkID := range got {
|
"__meta_dockerswarm_network_internal": "false",
|
||||||
networkIDs = append(networkIDs, networkID)
|
"__meta_dockerswarm_network_label_key1": "value1",
|
||||||
}
|
"__meta_dockerswarm_network_name": "ingress",
|
||||||
sort.Strings(networkIDs)
|
"__meta_dockerswarm_network_scope": "swarm",
|
||||||
var labelss []*promutils.Labels
|
}),
|
||||||
for _, networkID := range networkIDs {
|
|
||||||
labelss = append(labelss, got[networkID])
|
|
||||||
}
|
|
||||||
discoveryutils.TestEqualLabelss(t, labelss, tt.want)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
f(networks, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_parseNetworks(t *testing.T) {
|
func TestParseNetworks(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, resultExpected []network) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
result, err := parseNetworks([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseNetworks() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%v\nwant\n%v", result, resultExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// parse two networks
|
||||||
args args
|
data := `[
|
||||||
want []network
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse two networks",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`[
|
|
||||||
{
|
{
|
||||||
"Name": "ingress",
|
"Name": "ingress",
|
||||||
"Id": "qs0hog6ldlei9ct11pr3c77v1",
|
"Id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
@ -132,39 +124,25 @@ func Test_parseNetworks(t *testing.T) {
|
||||||
"key": "value"
|
"key": "value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]`),
|
]`
|
||||||
|
resultExpected := []network{
|
||||||
|
{
|
||||||
|
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
Ingress: true,
|
||||||
|
Scope: "swarm",
|
||||||
|
Name: "ingress",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"key1": "value1",
|
||||||
},
|
},
|
||||||
want: []network{
|
},
|
||||||
{
|
{
|
||||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
||||||
Ingress: true,
|
Scope: "local",
|
||||||
Scope: "swarm",
|
Name: "host",
|
||||||
Name: "ingress",
|
Labels: map[string]string{
|
||||||
Labels: map[string]string{
|
"key": "value",
|
||||||
"key1": "value1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
|
||||||
Scope: "local",
|
|
||||||
Name: "host",
|
|
||||||
Labels: map[string]string{
|
|
||||||
"key": "value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, resultExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseNetworks(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseNetworks() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseNetworks() \ngot %v, \nwant %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,32 +10,44 @@ import (
|
||||||
|
|
||||||
// See https://docs.docker.com/engine/api/v1.40/#tag/Node
|
// See https://docs.docker.com/engine/api/v1.40/#tag/Node
|
||||||
type node struct {
|
type node struct {
|
||||||
ID string
|
ID string
|
||||||
Spec struct {
|
Spec nodeSpec
|
||||||
Labels map[string]string
|
Description nodeDescription
|
||||||
Role string
|
Status nodeStatus
|
||||||
Availability string
|
ManagerStatus nodeManagerStatus
|
||||||
}
|
}
|
||||||
Description struct {
|
|
||||||
Hostname string
|
type nodeSpec struct {
|
||||||
Platform struct {
|
Labels map[string]string
|
||||||
Architecture string
|
Role string
|
||||||
OS string
|
Availability string
|
||||||
}
|
}
|
||||||
Engine struct {
|
|
||||||
EngineVersion string
|
type nodeDescription struct {
|
||||||
}
|
Hostname string
|
||||||
}
|
Platform nodePlatform
|
||||||
Status struct {
|
Engine nodeEngine
|
||||||
State string
|
}
|
||||||
Message string
|
|
||||||
Addr string
|
type nodePlatform struct {
|
||||||
}
|
Architecture string
|
||||||
ManagerStatus struct {
|
OS string
|
||||||
Leader bool
|
}
|
||||||
Reachability string
|
|
||||||
Addr string
|
type nodeEngine struct {
|
||||||
}
|
EngineVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeStatus struct {
|
||||||
|
State string
|
||||||
|
Message string
|
||||||
|
Addr string
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeManagerStatus struct {
|
||||||
|
Leader bool
|
||||||
|
Reachability string
|
||||||
|
Addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNodesLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
func getNodesLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
||||||
|
|
|
@ -8,20 +8,21 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseNodes(t *testing.T) {
|
func TestParseNodes(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, resultExpected []node) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
result, err := parseNodes([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseNodes() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
|
t.Fatalf("unexpected result;\ngot\n%v\nwant\n%v", result, resultExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// parse ok
|
||||||
args args
|
data := `[
|
||||||
want []node
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse ok",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`[
|
|
||||||
{
|
{
|
||||||
"ID": "qauwmifceyvqs0sipvzu8oslu",
|
"ID": "qauwmifceyvqs0sipvzu8oslu",
|
||||||
"Version": {
|
"Version": {
|
||||||
|
@ -51,131 +52,81 @@ func Test_parseNodes(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
`),
|
`
|
||||||
|
resultExpected := []node{
|
||||||
|
{
|
||||||
|
ID: "qauwmifceyvqs0sipvzu8oslu",
|
||||||
|
Spec: nodeSpec{
|
||||||
|
Role: "manager",
|
||||||
|
Availability: "active",
|
||||||
},
|
},
|
||||||
want: []node{
|
Status: nodeStatus{
|
||||||
{
|
State: "ready",
|
||||||
ID: "qauwmifceyvqs0sipvzu8oslu",
|
Addr: "172.31.40.97",
|
||||||
Spec: struct {
|
},
|
||||||
Labels map[string]string
|
Description: nodeDescription{
|
||||||
Role string
|
Hostname: "ip-172-31-40-97",
|
||||||
Availability string
|
Platform: nodePlatform{
|
||||||
}{Role: "manager", Availability: "active"},
|
Architecture: "x86_64",
|
||||||
Status: struct {
|
OS: "linux",
|
||||||
State string
|
},
|
||||||
Message string
|
Engine: nodeEngine{
|
||||||
Addr string
|
EngineVersion: "19.03.11",
|
||||||
}{State: "ready", Addr: "172.31.40.97"},
|
|
||||||
Description: struct {
|
|
||||||
Hostname string
|
|
||||||
Platform struct {
|
|
||||||
Architecture string
|
|
||||||
OS string
|
|
||||||
}
|
|
||||||
Engine struct{ EngineVersion string }
|
|
||||||
}{
|
|
||||||
Hostname: "ip-172-31-40-97",
|
|
||||||
Platform: struct {
|
|
||||||
Architecture string
|
|
||||||
OS string
|
|
||||||
}{
|
|
||||||
Architecture: "x86_64",
|
|
||||||
OS: "linux",
|
|
||||||
},
|
|
||||||
Engine: struct{ EngineVersion string }{
|
|
||||||
EngineVersion: "19.03.11",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, resultExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseNodes(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseNodes() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseNodes() \ngot %v, \nwant %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_addNodeLabels(t *testing.T) {
|
func TestAddNodeLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(nodes []node, port int, resultExpected []*promutils.Labels) {
|
||||||
nodes []node
|
t.Helper()
|
||||||
port int
|
|
||||||
|
result := addNodeLabels(nodes, port)
|
||||||
|
discoveryutils.TestEqualLabelss(t, result, resultExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// add labels to one node
|
||||||
args args
|
nodes := []node{
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "add labels to one node",
|
ID: "qauwmifceyvqs0sipvzu8oslu",
|
||||||
args: args{
|
Spec: nodeSpec{
|
||||||
nodes: []node{
|
Role: "manager",
|
||||||
{
|
Availability: "active",
|
||||||
ID: "qauwmifceyvqs0sipvzu8oslu",
|
},
|
||||||
Spec: struct {
|
Status: nodeStatus{
|
||||||
Labels map[string]string
|
State: "ready",
|
||||||
Role string
|
Addr: "172.31.40.97",
|
||||||
Availability string
|
},
|
||||||
}{Role: "manager", Availability: "active"},
|
Description: nodeDescription{
|
||||||
Status: struct {
|
Hostname: "ip-172-31-40-97",
|
||||||
State string
|
Platform: nodePlatform{
|
||||||
Message string
|
Architecture: "x86_64",
|
||||||
Addr string
|
OS: "linux",
|
||||||
}{State: "ready", Addr: "172.31.40.97"},
|
},
|
||||||
Description: struct {
|
Engine: nodeEngine{
|
||||||
Hostname string
|
EngineVersion: "19.03.11",
|
||||||
Platform struct {
|
},
|
||||||
Architecture string
|
|
||||||
OS string
|
|
||||||
}
|
|
||||||
Engine struct{ EngineVersion string }
|
|
||||||
}{
|
|
||||||
Hostname: "ip-172-31-40-97",
|
|
||||||
Platform: struct {
|
|
||||||
Architecture string
|
|
||||||
OS string
|
|
||||||
}{
|
|
||||||
Architecture: "x86_64",
|
|
||||||
OS: "linux",
|
|
||||||
},
|
|
||||||
Engine: struct{ EngineVersion string }{
|
|
||||||
EngineVersion: "19.03.11",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
port: 9100,
|
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "172.31.40.97:9100",
|
|
||||||
"__meta_dockerswarm_node_address": "172.31.40.97",
|
|
||||||
"__meta_dockerswarm_node_availability": "active",
|
|
||||||
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
|
||||||
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
|
||||||
"__meta_dockerswarm_node_manager_address": "",
|
|
||||||
"__meta_dockerswarm_node_manager_leader": "false",
|
|
||||||
"__meta_dockerswarm_node_manager_reachability": "",
|
|
||||||
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
|
||||||
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
|
||||||
"__meta_dockerswarm_node_platform_os": "linux",
|
|
||||||
"__meta_dockerswarm_node_role": "manager",
|
|
||||||
"__meta_dockerswarm_node_status": "ready",
|
|
||||||
})},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected := []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addNodeLabels(tt.args.nodes, tt.args.port)
|
"__address__": "172.31.40.97:9100",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_dockerswarm_node_address": "172.31.40.97",
|
||||||
})
|
"__meta_dockerswarm_node_availability": "active",
|
||||||
|
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
||||||
|
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
||||||
|
"__meta_dockerswarm_node_manager_address": "",
|
||||||
|
"__meta_dockerswarm_node_manager_leader": "false",
|
||||||
|
"__meta_dockerswarm_node_manager_reachability": "",
|
||||||
|
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
||||||
|
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
||||||
|
"__meta_dockerswarm_node_platform_os": "linux",
|
||||||
|
"__meta_dockerswarm_node_role": "manager",
|
||||||
|
"__meta_dockerswarm_node_status": "ready",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
f(nodes, 9100, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,31 +12,45 @@ import (
|
||||||
|
|
||||||
// https://docs.docker.com/engine/api/v1.40/#tag/Service
|
// https://docs.docker.com/engine/api/v1.40/#tag/Service
|
||||||
type service struct {
|
type service struct {
|
||||||
ID string
|
ID string
|
||||||
Spec struct {
|
Spec serviceSpec
|
||||||
Labels map[string]string
|
UpdateStatus serviceUpdateStatus
|
||||||
Name string
|
Endpoint serviceEndpoint
|
||||||
TaskTemplate struct {
|
}
|
||||||
ContainerSpec struct {
|
|
||||||
Hostname string
|
type serviceSpec struct {
|
||||||
Image string
|
Labels map[string]string
|
||||||
}
|
Name string
|
||||||
}
|
TaskTemplate taskTemplate
|
||||||
Mode struct {
|
Mode serviceSpecMode
|
||||||
Global interface{}
|
}
|
||||||
Replicated interface{}
|
|
||||||
}
|
type taskTemplate struct {
|
||||||
}
|
ContainerSpec containerSpec
|
||||||
UpdateStatus struct {
|
}
|
||||||
State string
|
|
||||||
}
|
type containerSpec struct {
|
||||||
Endpoint struct {
|
Hostname string
|
||||||
Ports []portConfig
|
Image string
|
||||||
VirtualIPs []struct {
|
}
|
||||||
NetworkID string
|
|
||||||
Addr string
|
type serviceSpecMode struct {
|
||||||
}
|
Global interface{}
|
||||||
}
|
Replicated interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type serviceUpdateStatus struct {
|
||||||
|
State string
|
||||||
|
}
|
||||||
|
|
||||||
|
type serviceEndpoint struct {
|
||||||
|
Ports []portConfig
|
||||||
|
VirtualIPs []virtualIP
|
||||||
|
}
|
||||||
|
|
||||||
|
type virtualIP struct {
|
||||||
|
NetworkID string
|
||||||
|
Addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
type portConfig struct {
|
type portConfig struct {
|
||||||
|
|
|
@ -8,20 +8,21 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseServicesResponse(t *testing.T) {
|
func TestParseServicesResponse(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, servicesExpected []service) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
services, err := parseServicesResponse([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseServicesResponse() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(services, servicesExpected) {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%v\nwant\n%v", services, servicesExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// parse ok
|
||||||
args args
|
data := `[
|
||||||
want []service
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse ok",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`[
|
|
||||||
{
|
{
|
||||||
"ID": "tgsci5gd31aai3jyudv98pqxf",
|
"ID": "tgsci5gd31aai3jyudv98pqxf",
|
||||||
"Version": {
|
"Version": {
|
||||||
|
@ -87,202 +88,113 @@ func Test_parseServicesResponse(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]`),
|
]`
|
||||||
|
|
||||||
|
servicesExpected := []service{
|
||||||
|
{
|
||||||
|
ID: "tgsci5gd31aai3jyudv98pqxf",
|
||||||
|
Spec: serviceSpec{
|
||||||
|
Labels: map[string]string{},
|
||||||
|
Name: "redis2",
|
||||||
|
TaskTemplate: taskTemplate{
|
||||||
|
ContainerSpec: containerSpec{
|
||||||
|
Image: "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Mode: serviceSpecMode{
|
||||||
|
Replicated: map[string]interface{}{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
want: []service{
|
Endpoint: serviceEndpoint{
|
||||||
{
|
Ports: []portConfig{
|
||||||
ID: "tgsci5gd31aai3jyudv98pqxf",
|
{
|
||||||
Spec: struct {
|
Protocol: "tcp",
|
||||||
Labels map[string]string
|
PublishMode: "ingress",
|
||||||
Name string
|
PublishedPort: 8081,
|
||||||
TaskTemplate struct {
|
|
||||||
ContainerSpec struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Mode struct {
|
|
||||||
Global interface{}
|
|
||||||
Replicated interface{}
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Labels: map[string]string{},
|
|
||||||
Name: "redis2",
|
|
||||||
TaskTemplate: struct {
|
|
||||||
ContainerSpec struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
ContainerSpec: struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}{
|
|
||||||
Hostname: "",
|
|
||||||
Image: "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Mode: struct {
|
|
||||||
Global interface{}
|
|
||||||
Replicated interface{}
|
|
||||||
}{
|
|
||||||
Replicated: map[string]interface{}{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Endpoint: struct {
|
|
||||||
Ports []portConfig
|
|
||||||
VirtualIPs []struct {
|
|
||||||
NetworkID string
|
|
||||||
Addr string
|
|
||||||
}
|
|
||||||
}{Ports: []portConfig{
|
|
||||||
{
|
|
||||||
Protocol: "tcp",
|
|
||||||
PublishMode: "ingress",
|
|
||||||
PublishedPort: 8081,
|
|
||||||
},
|
|
||||||
}, VirtualIPs: []struct {
|
|
||||||
NetworkID string
|
|
||||||
Addr string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
Addr: "10.0.0.3/24",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
VirtualIPs: []virtualIP{
|
||||||
|
{
|
||||||
|
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
Addr: "10.0.0.3/24",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, servicesExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseServicesResponse(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseServicesResponse() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseServicesResponse() \ngot %v, \nwant %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_addServicesLabels(t *testing.T) {
|
func TestAddServicesLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(services []service, networksLabels map[string]*promutils.Labels, labelssExpected []*promutils.Labels) {
|
||||||
services []service
|
t.Helper()
|
||||||
networksLabels map[string]*promutils.Labels
|
|
||||||
port int
|
labelss := addServicesLabels(services, networksLabels, 9100)
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// add 2 services with network labels join
|
||||||
args args
|
services := []service{
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "add 2 services with network labels join",
|
ID: "tgsci5gd31aai3jyudv98pqxf",
|
||||||
args: args{
|
Spec: serviceSpec{
|
||||||
port: 9100,
|
Labels: map[string]string{},
|
||||||
networksLabels: map[string]*promutils.Labels{
|
Name: "redis2",
|
||||||
"qs0hog6ldlei9ct11pr3c77v1": promutils.NewLabelsFromMap(map[string]string{
|
TaskTemplate: taskTemplate{
|
||||||
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
ContainerSpec: containerSpec{
|
||||||
"__meta_dockerswarm_network_ingress": "true",
|
Hostname: "node1",
|
||||||
"__meta_dockerswarm_network_internal": "false",
|
Image: "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
||||||
"__meta_dockerswarm_network_label_key1": "value1",
|
},
|
||||||
"__meta_dockerswarm_network_name": "ingress",
|
|
||||||
"__meta_dockerswarm_network_scope": "swarm",
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
services: []service{
|
Mode: serviceSpecMode{
|
||||||
|
Replicated: map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Endpoint: serviceEndpoint{
|
||||||
|
Ports: []portConfig{
|
||||||
{
|
{
|
||||||
ID: "tgsci5gd31aai3jyudv98pqxf",
|
Protocol: "tcp",
|
||||||
Spec: struct {
|
Name: "redis",
|
||||||
Labels map[string]string
|
PublishMode: "ingress",
|
||||||
Name string
|
},
|
||||||
TaskTemplate struct {
|
},
|
||||||
ContainerSpec struct {
|
VirtualIPs: []virtualIP{
|
||||||
Hostname string
|
{
|
||||||
Image string
|
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
}
|
Addr: "10.0.0.3/24",
|
||||||
}
|
|
||||||
Mode struct {
|
|
||||||
Global interface{}
|
|
||||||
Replicated interface{}
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Labels: map[string]string{},
|
|
||||||
Name: "redis2",
|
|
||||||
TaskTemplate: struct {
|
|
||||||
ContainerSpec struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
ContainerSpec: struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}{
|
|
||||||
Hostname: "node1",
|
|
||||||
Image: "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Mode: struct {
|
|
||||||
Global interface{}
|
|
||||||
Replicated interface{}
|
|
||||||
}{
|
|
||||||
Replicated: map[string]interface{}{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Endpoint: struct {
|
|
||||||
Ports []portConfig
|
|
||||||
VirtualIPs []struct {
|
|
||||||
NetworkID string
|
|
||||||
Addr string
|
|
||||||
}
|
|
||||||
}{Ports: []portConfig{
|
|
||||||
{
|
|
||||||
Protocol: "tcp",
|
|
||||||
Name: "redis",
|
|
||||||
PublishMode: "ingress",
|
|
||||||
},
|
|
||||||
}, VirtualIPs: []struct {
|
|
||||||
NetworkID string
|
|
||||||
Addr string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
Addr: "10.0.0.3/24",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "10.0.0.3:0",
|
|
||||||
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
"__meta_dockerswarm_network_ingress": "true",
|
|
||||||
"__meta_dockerswarm_network_internal": "false",
|
|
||||||
"__meta_dockerswarm_network_label_key1": "value1",
|
|
||||||
"__meta_dockerswarm_network_name": "ingress",
|
|
||||||
"__meta_dockerswarm_network_scope": "swarm",
|
|
||||||
"__meta_dockerswarm_service_endpoint_port_name": "redis",
|
|
||||||
"__meta_dockerswarm_service_endpoint_port_publish_mode": "ingress",
|
|
||||||
"__meta_dockerswarm_service_id": "tgsci5gd31aai3jyudv98pqxf",
|
|
||||||
"__meta_dockerswarm_service_mode": "replicated",
|
|
||||||
"__meta_dockerswarm_service_name": "redis2",
|
|
||||||
"__meta_dockerswarm_service_task_container_hostname": "node1",
|
|
||||||
"__meta_dockerswarm_service_task_container_image": "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
|
||||||
"__meta_dockerswarm_service_updating_status": "",
|
|
||||||
})},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
networksLabels := map[string]*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
"qs0hog6ldlei9ct11pr3c77v1": promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addServicesLabels(tt.args.services, tt.args.networksLabels, tt.args.port)
|
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_dockerswarm_network_ingress": "true",
|
||||||
})
|
"__meta_dockerswarm_network_internal": "false",
|
||||||
|
"__meta_dockerswarm_network_label_key1": "value1",
|
||||||
|
"__meta_dockerswarm_network_name": "ingress",
|
||||||
|
"__meta_dockerswarm_network_scope": "swarm",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
labelssExpected := []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "10.0.0.3:0",
|
||||||
|
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
"__meta_dockerswarm_network_ingress": "true",
|
||||||
|
"__meta_dockerswarm_network_internal": "false",
|
||||||
|
"__meta_dockerswarm_network_label_key1": "value1",
|
||||||
|
"__meta_dockerswarm_network_name": "ingress",
|
||||||
|
"__meta_dockerswarm_network_scope": "swarm",
|
||||||
|
"__meta_dockerswarm_service_endpoint_port_name": "redis",
|
||||||
|
"__meta_dockerswarm_service_endpoint_port_publish_mode": "ingress",
|
||||||
|
"__meta_dockerswarm_service_id": "tgsci5gd31aai3jyudv98pqxf",
|
||||||
|
"__meta_dockerswarm_service_mode": "replicated",
|
||||||
|
"__meta_dockerswarm_service_name": "redis2",
|
||||||
|
"__meta_dockerswarm_service_task_container_hostname": "node1",
|
||||||
|
"__meta_dockerswarm_service_task_container_image": "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
||||||
|
"__meta_dockerswarm_service_updating_status": "",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(services, networksLabels, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,27 +17,37 @@ type task struct {
|
||||||
ServiceID string
|
ServiceID string
|
||||||
NodeID string
|
NodeID string
|
||||||
DesiredState string
|
DesiredState string
|
||||||
NetworksAttachments []struct {
|
NetworksAttachments []networkAttachment
|
||||||
Addresses []string
|
Status taskStatus
|
||||||
Network struct {
|
Spec taskSpec
|
||||||
ID string
|
Slot int
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Status struct {
|
type networkAttachment struct {
|
||||||
State string
|
Addresses []string
|
||||||
ContainerStatus struct {
|
Network network
|
||||||
ContainerID string
|
}
|
||||||
}
|
|
||||||
PortStatus struct {
|
type taskStatus struct {
|
||||||
Ports []portConfig
|
State string
|
||||||
}
|
ContainerStatus containerStatus
|
||||||
}
|
PortStatus portStatus
|
||||||
Spec struct {
|
}
|
||||||
ContainerSpec struct {
|
|
||||||
Labels map[string]string
|
type containerStatus struct {
|
||||||
}
|
ContainerID string
|
||||||
}
|
}
|
||||||
Slot int
|
|
||||||
|
type portStatus struct {
|
||||||
|
Ports []portConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type taskSpec struct {
|
||||||
|
ContainerSpec taskContainerSpec
|
||||||
|
}
|
||||||
|
|
||||||
|
type taskContainerSpec struct {
|
||||||
|
Labels map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTasksLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
func getTasksLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
||||||
|
|
|
@ -8,20 +8,21 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseTasks(t *testing.T) {
|
func TestParseTasks(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, tasksExpected []task) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
tasks, err := parseTasks([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseTasks() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tasks, tasksExpected) {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%v\nwant\n%v", tasks, tasksExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// parse ok
|
||||||
args args
|
data := `[
|
||||||
want []task
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse ok",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`[
|
|
||||||
{
|
{
|
||||||
"ID": "t4rdm7j2y9yctbrksiwvsgpu5",
|
"ID": "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||||
"Version": {
|
"Version": {
|
||||||
|
@ -63,297 +64,217 @@ func Test_parseTasks(t *testing.T) {
|
||||||
"DesiredState": "running"
|
"DesiredState": "running"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
`),
|
`
|
||||||
},
|
|
||||||
want: []task{
|
tasksExpected := []task{
|
||||||
{
|
{
|
||||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||||
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
||||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||||
Spec: struct {
|
Spec: taskSpec{
|
||||||
ContainerSpec struct {
|
ContainerSpec: taskContainerSpec{
|
||||||
Labels map[string]string
|
Labels: map[string]string{
|
||||||
}
|
"label1": "value1",
|
||||||
}{
|
|
||||||
ContainerSpec: struct {
|
|
||||||
Labels map[string]string
|
|
||||||
}{
|
|
||||||
Labels: map[string]string{
|
|
||||||
"label1": "value1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
DesiredState: "running",
|
|
||||||
Slot: 1,
|
|
||||||
Status: struct {
|
|
||||||
State string
|
|
||||||
ContainerStatus struct{ ContainerID string }
|
|
||||||
PortStatus struct{ Ports []portConfig }
|
|
||||||
}{
|
|
||||||
State: "running",
|
|
||||||
ContainerStatus: struct{ ContainerID string }{
|
|
||||||
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
|
||||||
},
|
|
||||||
PortStatus: struct{ Ports []portConfig }{}},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DesiredState: "running",
|
||||||
|
Slot: 1,
|
||||||
|
Status: taskStatus{
|
||||||
|
State: "running",
|
||||||
|
ContainerStatus: containerStatus{
|
||||||
|
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
||||||
|
},
|
||||||
|
PortStatus: portStatus{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, tasksExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseTasks(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseTasks() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseTasks() got\n%v\nwant\n%v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_addTasksLabels(t *testing.T) {
|
func TestAddTasksLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(tasks []task, nodesLabels []*promutils.Labels, networkLabels map[string]*promutils.Labels, services []service, labelssExpected []*promutils.Labels) {
|
||||||
tasks []task
|
t.Helper()
|
||||||
nodesLabels []*promutils.Labels
|
|
||||||
servicesLabels []*promutils.Labels
|
labelss := addTasksLabels(tasks, nodesLabels, nil, networkLabels, services, 9100)
|
||||||
networksLabels map[string]*promutils.Labels
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
services []service
|
|
||||||
port int
|
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// adds 1 task with nodes labels
|
||||||
args args
|
tasks := []task{
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "adds 1 task with nodes labels",
|
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||||
args: args{
|
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
||||||
port: 9100,
|
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||||
tasks: []task{
|
DesiredState: "running",
|
||||||
{
|
Slot: 1,
|
||||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
Status: taskStatus{
|
||||||
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
State: "running",
|
||||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
ContainerStatus: containerStatus{
|
||||||
DesiredState: "running",
|
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
||||||
Slot: 1,
|
},
|
||||||
Status: struct {
|
PortStatus: portStatus{
|
||||||
State string
|
Ports: []portConfig{
|
||||||
ContainerStatus struct{ ContainerID string }
|
{
|
||||||
PortStatus struct{ Ports []portConfig }
|
PublishMode: "ingress",
|
||||||
}{
|
Name: "redis",
|
||||||
State: "running",
|
Protocol: "tcp",
|
||||||
ContainerStatus: struct{ ContainerID string }{
|
PublishedPort: 6379,
|
||||||
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
},
|
||||||
},
|
|
||||||
PortStatus: struct{ Ports []portConfig }{
|
|
||||||
Ports: []portConfig{
|
|
||||||
{
|
|
||||||
PublishMode: "ingress",
|
|
||||||
Name: "redis",
|
|
||||||
Protocol: "tcp",
|
|
||||||
PublishedPort: 6379,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
},
|
}},
|
||||||
nodesLabels: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "172.31.40.97:9100",
|
|
||||||
"__meta_dockerswarm_node_address": "172.31.40.97",
|
|
||||||
"__meta_dockerswarm_node_availability": "active",
|
|
||||||
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
|
||||||
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
|
||||||
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
|
||||||
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
|
||||||
"__meta_dockerswarm_node_platform_os": "linux",
|
|
||||||
"__meta_dockerswarm_node_role": "manager",
|
|
||||||
"__meta_dockerswarm_node_status": "ready",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "172.31.40.97:6379",
|
|
||||||
"__meta_dockerswarm_node_address": "172.31.40.97",
|
|
||||||
"__meta_dockerswarm_node_availability": "active",
|
|
||||||
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
|
||||||
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
|
||||||
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
|
||||||
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
|
||||||
"__meta_dockerswarm_node_platform_os": "linux",
|
|
||||||
"__meta_dockerswarm_node_role": "manager",
|
|
||||||
"__meta_dockerswarm_node_status": "ready",
|
|
||||||
"__meta_dockerswarm_task_container_id": "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
|
||||||
"__meta_dockerswarm_task_desired_state": "running",
|
|
||||||
"__meta_dockerswarm_task_id": "t4rdm7j2y9yctbrksiwvsgpu5",
|
|
||||||
"__meta_dockerswarm_task_port_publish_mode": "ingress",
|
|
||||||
"__meta_dockerswarm_task_slot": "1",
|
|
||||||
"__meta_dockerswarm_task_state": "running",
|
|
||||||
})},
|
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesLabels := []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "172.31.40.97:9100",
|
||||||
|
"__meta_dockerswarm_node_address": "172.31.40.97",
|
||||||
|
"__meta_dockerswarm_node_availability": "active",
|
||||||
|
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
||||||
|
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
||||||
|
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
||||||
|
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
||||||
|
"__meta_dockerswarm_node_platform_os": "linux",
|
||||||
|
"__meta_dockerswarm_node_role": "manager",
|
||||||
|
"__meta_dockerswarm_node_status": "ready",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
labelssExpected := []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "172.31.40.97:6379",
|
||||||
|
"__meta_dockerswarm_node_address": "172.31.40.97",
|
||||||
|
"__meta_dockerswarm_node_availability": "active",
|
||||||
|
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
||||||
|
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
||||||
|
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
||||||
|
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
||||||
|
"__meta_dockerswarm_node_platform_os": "linux",
|
||||||
|
"__meta_dockerswarm_node_role": "manager",
|
||||||
|
"__meta_dockerswarm_node_status": "ready",
|
||||||
|
"__meta_dockerswarm_task_container_id": "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
||||||
|
"__meta_dockerswarm_task_desired_state": "running",
|
||||||
|
"__meta_dockerswarm_task_id": "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||||
|
"__meta_dockerswarm_task_port_publish_mode": "ingress",
|
||||||
|
"__meta_dockerswarm_task_slot": "1",
|
||||||
|
"__meta_dockerswarm_task_state": "running",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(tasks, nodesLabels, nil, nil, labelssExpected)
|
||||||
|
|
||||||
|
// adds 1 task with nodes, network and services labels
|
||||||
|
tasks = []task{
|
||||||
{
|
{
|
||||||
name: "adds 1 task with nodes, network and services labels",
|
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||||
args: args{
|
ServiceID: "tgsci5gd31aai3jyudv98pqxf",
|
||||||
port: 9100,
|
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||||
tasks: []task{
|
DesiredState: "running",
|
||||||
{
|
Slot: 1,
|
||||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
NetworksAttachments: []networkAttachment{
|
||||||
ServiceID: "tgsci5gd31aai3jyudv98pqxf",
|
{
|
||||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
Network: network{
|
||||||
DesiredState: "running",
|
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
Slot: 1,
|
|
||||||
NetworksAttachments: []struct {
|
|
||||||
Addresses []string
|
|
||||||
Network struct{ ID string }
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Network: struct {
|
|
||||||
ID string
|
|
||||||
}{
|
|
||||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
},
|
|
||||||
Addresses: []string{"10.10.15.15/24"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Status: struct {
|
|
||||||
State string
|
|
||||||
ContainerStatus struct{ ContainerID string }
|
|
||||||
PortStatus struct{ Ports []portConfig }
|
|
||||||
}{
|
|
||||||
State: "running",
|
|
||||||
ContainerStatus: struct{ ContainerID string }{
|
|
||||||
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
|
||||||
},
|
|
||||||
PortStatus: struct{ Ports []portConfig }{}},
|
|
||||||
},
|
},
|
||||||
|
Addresses: []string{"10.10.15.15/24"},
|
||||||
},
|
},
|
||||||
networksLabels: map[string]*promutils.Labels{
|
|
||||||
"qs0hog6ldlei9ct11pr3c77v1": promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
"__meta_dockerswarm_network_ingress": "true",
|
|
||||||
"__meta_dockerswarm_network_internal": "false",
|
|
||||||
"__meta_dockerswarm_network_label_key1": "value1",
|
|
||||||
"__meta_dockerswarm_network_name": "ingress",
|
|
||||||
"__meta_dockerswarm_network_scope": "swarm",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
nodesLabels: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "172.31.40.97:9100",
|
|
||||||
"__meta_dockerswarm_node_address": "172.31.40.97",
|
|
||||||
"__meta_dockerswarm_node_availability": "active",
|
|
||||||
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
|
||||||
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
|
||||||
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
|
||||||
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
|
||||||
"__meta_dockerswarm_node_platform_os": "linux",
|
|
||||||
"__meta_dockerswarm_node_role": "manager",
|
|
||||||
"__meta_dockerswarm_node_status": "ready",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
services: []service{
|
|
||||||
{
|
|
||||||
ID: "tgsci5gd31aai3jyudv98pqxf",
|
|
||||||
Spec: struct {
|
|
||||||
Labels map[string]string
|
|
||||||
Name string
|
|
||||||
TaskTemplate struct {
|
|
||||||
ContainerSpec struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Mode struct {
|
|
||||||
Global interface{}
|
|
||||||
Replicated interface{}
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Labels: map[string]string{},
|
|
||||||
Name: "redis2",
|
|
||||||
TaskTemplate: struct {
|
|
||||||
ContainerSpec struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
ContainerSpec: struct {
|
|
||||||
Hostname string
|
|
||||||
Image string
|
|
||||||
}{
|
|
||||||
Hostname: "node1",
|
|
||||||
Image: "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Mode: struct {
|
|
||||||
Global interface{}
|
|
||||||
Replicated interface{}
|
|
||||||
}{
|
|
||||||
Replicated: map[string]interface{}{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Endpoint: struct {
|
|
||||||
Ports []portConfig
|
|
||||||
VirtualIPs []struct {
|
|
||||||
NetworkID string
|
|
||||||
Addr string
|
|
||||||
}
|
|
||||||
}{
|
|
||||||
Ports: []portConfig{
|
|
||||||
{
|
|
||||||
Protocol: "tcp",
|
|
||||||
Name: "redis",
|
|
||||||
PublishMode: "ingress",
|
|
||||||
PublishedPort: 6379,
|
|
||||||
},
|
|
||||||
}, VirtualIPs: []struct {
|
|
||||||
NetworkID string
|
|
||||||
Addr string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
|
||||||
Addr: "10.0.0.3/24",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
servicesLabels: []*promutils.Labels{},
|
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
Status: taskStatus{
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
State: "running",
|
||||||
"__address__": "10.10.15.15:6379",
|
ContainerStatus: containerStatus{
|
||||||
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
||||||
"__meta_dockerswarm_network_ingress": "true",
|
},
|
||||||
"__meta_dockerswarm_network_internal": "false",
|
PortStatus: portStatus{},
|
||||||
"__meta_dockerswarm_network_label_key1": "value1",
|
|
||||||
"__meta_dockerswarm_network_name": "ingress",
|
|
||||||
"__meta_dockerswarm_network_scope": "swarm",
|
|
||||||
"__meta_dockerswarm_node_address": "172.31.40.97",
|
|
||||||
"__meta_dockerswarm_node_availability": "active",
|
|
||||||
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
|
||||||
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
|
||||||
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
|
||||||
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
|
||||||
"__meta_dockerswarm_node_platform_os": "linux",
|
|
||||||
"__meta_dockerswarm_node_role": "manager",
|
|
||||||
"__meta_dockerswarm_node_status": "ready",
|
|
||||||
"__meta_dockerswarm_task_container_id": "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
|
||||||
"__meta_dockerswarm_task_desired_state": "running",
|
|
||||||
"__meta_dockerswarm_task_id": "t4rdm7j2y9yctbrksiwvsgpu5",
|
|
||||||
"__meta_dockerswarm_task_port_publish_mode": "ingress",
|
|
||||||
"__meta_dockerswarm_task_slot": "1",
|
|
||||||
"__meta_dockerswarm_task_state": "running",
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
networksLabels := map[string]*promutils.Labels{
|
||||||
got := addTasksLabels(tt.args.tasks, tt.args.nodesLabels, tt.args.servicesLabels, tt.args.networksLabels, tt.args.services, tt.args.port)
|
"qs0hog6ldlei9ct11pr3c77v1": promutils.NewLabelsFromMap(map[string]string{
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
})
|
"__meta_dockerswarm_network_ingress": "true",
|
||||||
|
"__meta_dockerswarm_network_internal": "false",
|
||||||
|
"__meta_dockerswarm_network_label_key1": "value1",
|
||||||
|
"__meta_dockerswarm_network_name": "ingress",
|
||||||
|
"__meta_dockerswarm_network_scope": "swarm",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodesLabels = []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "172.31.40.97:9100",
|
||||||
|
"__meta_dockerswarm_node_address": "172.31.40.97",
|
||||||
|
"__meta_dockerswarm_node_availability": "active",
|
||||||
|
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
||||||
|
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
||||||
|
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
||||||
|
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
||||||
|
"__meta_dockerswarm_node_platform_os": "linux",
|
||||||
|
"__meta_dockerswarm_node_role": "manager",
|
||||||
|
"__meta_dockerswarm_node_status": "ready",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
services := []service{
|
||||||
|
{
|
||||||
|
ID: "tgsci5gd31aai3jyudv98pqxf",
|
||||||
|
Spec: serviceSpec{
|
||||||
|
Labels: map[string]string{},
|
||||||
|
Name: "redis2",
|
||||||
|
TaskTemplate: taskTemplate{
|
||||||
|
ContainerSpec: containerSpec{
|
||||||
|
Hostname: "node1",
|
||||||
|
Image: "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Mode: serviceSpecMode{
|
||||||
|
Replicated: map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Endpoint: serviceEndpoint{
|
||||||
|
Ports: []portConfig{
|
||||||
|
{
|
||||||
|
Protocol: "tcp",
|
||||||
|
Name: "redis",
|
||||||
|
PublishMode: "ingress",
|
||||||
|
PublishedPort: 6379,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VirtualIPs: []virtualIP{
|
||||||
|
{
|
||||||
|
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
Addr: "10.0.0.3/24",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
labelssExpected = []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "10.10.15.15:6379",
|
||||||
|
"__meta_dockerswarm_network_id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||||
|
"__meta_dockerswarm_network_ingress": "true",
|
||||||
|
"__meta_dockerswarm_network_internal": "false",
|
||||||
|
"__meta_dockerswarm_network_label_key1": "value1",
|
||||||
|
"__meta_dockerswarm_network_name": "ingress",
|
||||||
|
"__meta_dockerswarm_network_scope": "swarm",
|
||||||
|
"__meta_dockerswarm_node_address": "172.31.40.97",
|
||||||
|
"__meta_dockerswarm_node_availability": "active",
|
||||||
|
"__meta_dockerswarm_node_engine_version": "19.03.11",
|
||||||
|
"__meta_dockerswarm_node_hostname": "ip-172-31-40-97",
|
||||||
|
"__meta_dockerswarm_node_id": "qauwmifceyvqs0sipvzu8oslu",
|
||||||
|
"__meta_dockerswarm_node_platform_architecture": "x86_64",
|
||||||
|
"__meta_dockerswarm_node_platform_os": "linux",
|
||||||
|
"__meta_dockerswarm_node_role": "manager",
|
||||||
|
"__meta_dockerswarm_node_status": "ready",
|
||||||
|
"__meta_dockerswarm_task_container_id": "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
||||||
|
"__meta_dockerswarm_task_desired_state": "running",
|
||||||
|
"__meta_dockerswarm_task_id": "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||||
|
"__meta_dockerswarm_task_port_publish_mode": "ingress",
|
||||||
|
"__meta_dockerswarm_task_slot": "1",
|
||||||
|
"__meta_dockerswarm_task_state": "running",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(tasks, nodesLabels, networksLabels, services, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,21 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseAPIResponse(t *testing.T) {
|
func TestParseAPIResponse(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, resultExpected *applications) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
result, err := parseAPIResponse([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseAPIResponse() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%v\nwant\n%v", result, resultExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// parse ok 1 app with instance
|
||||||
args args
|
data := `<applications>
|
||||||
want *applications
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse ok 1 app with instance",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`<applications>
|
|
||||||
<versions__delta>1</versions__delta>
|
<versions__delta>1</versions__delta>
|
||||||
<apps__hashcode>UP_1_</apps__hashcode>
|
<apps__hashcode>UP_1_</apps__hashcode>
|
||||||
<application>
|
<application>
|
||||||
|
@ -55,53 +56,40 @@ func Test_parseAPIResponse(t *testing.T) {
|
||||||
<actionType>ADDED</actionType>
|
<actionType>ADDED</actionType>
|
||||||
</instance>
|
</instance>
|
||||||
</application>
|
</application>
|
||||||
</applications>`),
|
</applications>`
|
||||||
},
|
|
||||||
want: &applications{
|
resultExpected := &applications{
|
||||||
Applications: []Application{
|
Applications: []Application{
|
||||||
|
{
|
||||||
|
Name: "HELLO-NETFLIX-OSS",
|
||||||
|
Instances: []Instance{
|
||||||
{
|
{
|
||||||
Name: "HELLO-NETFLIX-OSS",
|
HostName: "98de25ebef42",
|
||||||
Instances: []Instance{
|
HomePageURL: "http://98de25ebef42:8080/",
|
||||||
{
|
StatusPageURL: "http://98de25ebef42:8080/Status",
|
||||||
HostName: "98de25ebef42",
|
HealthCheckURL: "http://98de25ebef42:8080/healthcheck",
|
||||||
HomePageURL: "http://98de25ebef42:8080/",
|
App: "HELLO-NETFLIX-OSS",
|
||||||
StatusPageURL: "http://98de25ebef42:8080/Status",
|
IPAddr: "10.10.0.3",
|
||||||
HealthCheckURL: "http://98de25ebef42:8080/healthcheck",
|
VipAddress: "HELLO-NETFLIX-OSS",
|
||||||
App: "HELLO-NETFLIX-OSS",
|
SecureVipAddress: "",
|
||||||
IPAddr: "10.10.0.3",
|
Status: "UP",
|
||||||
VipAddress: "HELLO-NETFLIX-OSS",
|
Port: Port{
|
||||||
SecureVipAddress: "",
|
Enabled: true,
|
||||||
Status: "UP",
|
Port: 8080,
|
||||||
Port: Port{
|
|
||||||
Enabled: true,
|
|
||||||
Port: 8080,
|
|
||||||
},
|
|
||||||
SecurePort: Port{
|
|
||||||
Port: 443,
|
|
||||||
},
|
|
||||||
DataCenterInfo: DataCenterInfo{
|
|
||||||
Name: "MyOwn",
|
|
||||||
},
|
|
||||||
Metadata: MetaData{},
|
|
||||||
CountryID: 1,
|
|
||||||
InstanceID: "",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
SecurePort: Port{
|
||||||
|
Port: 443,
|
||||||
|
},
|
||||||
|
DataCenterInfo: DataCenterInfo{
|
||||||
|
Name: "MyOwn",
|
||||||
|
},
|
||||||
|
Metadata: MetaData{},
|
||||||
|
CountryID: 1,
|
||||||
|
InstanceID: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, resultExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseAPIResponse(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseAPIResponse() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("unxpected response for parseAPIResponse() \ngot = %v, \nwant %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,74 +7,65 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_addInstanceLabels(t *testing.T) {
|
func TestAddInstanceLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(applications *applications, labelssExpected []*promutils.Labels) {
|
||||||
applications *applications
|
t.Helper()
|
||||||
|
|
||||||
|
labelss := addInstanceLabels(applications)
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// one application
|
||||||
args args
|
applications := &applications{
|
||||||
want []*promutils.Labels
|
Applications: []Application{
|
||||||
}{
|
{
|
||||||
{
|
Name: "test-app",
|
||||||
name: "1 application",
|
Instances: []Instance{
|
||||||
args: args{
|
{
|
||||||
applications: &applications{
|
Status: "Ok",
|
||||||
Applications: []Application{
|
HealthCheckURL: "some-url",
|
||||||
{
|
HomePageURL: "some-home-url",
|
||||||
Name: "test-app",
|
StatusPageURL: "some-status-url",
|
||||||
Instances: []Instance{
|
HostName: "host-1",
|
||||||
|
IPAddr: "10.15.11.11",
|
||||||
|
CountryID: 5,
|
||||||
|
VipAddress: "10.15.11.11",
|
||||||
|
InstanceID: "some-id",
|
||||||
|
Metadata: MetaData{
|
||||||
|
Items: []Tag{
|
||||||
{
|
{
|
||||||
Status: "Ok",
|
Content: "value-1",
|
||||||
HealthCheckURL: "some-url",
|
XMLName: struct{ Space, Local string }{Local: "key-1"},
|
||||||
HomePageURL: "some-home-url",
|
|
||||||
StatusPageURL: "some-status-url",
|
|
||||||
HostName: "host-1",
|
|
||||||
IPAddr: "10.15.11.11",
|
|
||||||
CountryID: 5,
|
|
||||||
VipAddress: "10.15.11.11",
|
|
||||||
InstanceID: "some-id",
|
|
||||||
Metadata: MetaData{Items: []Tag{
|
|
||||||
{
|
|
||||||
Content: "value-1",
|
|
||||||
XMLName: struct{ Space, Local string }{Local: "key-1"},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
Port: Port{
|
|
||||||
Port: 9100,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Port: Port{
|
||||||
|
Port: 9100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "host-1:9100",
|
|
||||||
"instance": "some-id",
|
|
||||||
"__meta_eureka_app_instance_hostname": "host-1",
|
|
||||||
"__meta_eureka_app_name": "test-app",
|
|
||||||
"__meta_eureka_app_instance_healthcheck_url": "some-url",
|
|
||||||
"__meta_eureka_app_instance_ip_addr": "10.15.11.11",
|
|
||||||
"__meta_eureka_app_instance_vip_address": "10.15.11.11",
|
|
||||||
"__meta_eureka_app_instance_secure_vip_address": "",
|
|
||||||
"__meta_eureka_app_instance_country_id": "5",
|
|
||||||
"__meta_eureka_app_instance_homepage_url": "some-home-url",
|
|
||||||
"__meta_eureka_app_instance_statuspage_url": "some-status-url",
|
|
||||||
"__meta_eureka_app_instance_id": "some-id",
|
|
||||||
"__meta_eureka_app_instance_metadata_key_1": "value-1",
|
|
||||||
"__meta_eureka_app_instance_port": "9100",
|
|
||||||
"__meta_eureka_app_instance_port_enabled": "false",
|
|
||||||
"__meta_eureka_app_instance_status": "Ok",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected := []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addInstanceLabels(tt.args.applications)
|
"__address__": "host-1:9100",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"instance": "some-id",
|
||||||
})
|
"__meta_eureka_app_instance_hostname": "host-1",
|
||||||
|
"__meta_eureka_app_name": "test-app",
|
||||||
|
"__meta_eureka_app_instance_healthcheck_url": "some-url",
|
||||||
|
"__meta_eureka_app_instance_ip_addr": "10.15.11.11",
|
||||||
|
"__meta_eureka_app_instance_vip_address": "10.15.11.11",
|
||||||
|
"__meta_eureka_app_instance_secure_vip_address": "",
|
||||||
|
"__meta_eureka_app_instance_country_id": "5",
|
||||||
|
"__meta_eureka_app_instance_homepage_url": "some-home-url",
|
||||||
|
"__meta_eureka_app_instance_statuspage_url": "some-status-url",
|
||||||
|
"__meta_eureka_app_instance_id": "some-id",
|
||||||
|
"__meta_eureka_app_instance_metadata_key_1": "value-1",
|
||||||
|
"__meta_eureka_app_instance_port": "9100",
|
||||||
|
"__meta_eureka_app_instance_port_enabled": "false",
|
||||||
|
"__meta_eureka_app_instance_status": "Ok",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
f(applications, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,45 +7,30 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseAPIResponse(t *testing.T) {
|
func TestParseAPIResponse(t *testing.T) {
|
||||||
type args struct {
|
f := func(data, path string, resultExpected []httpGroupTarget) {
|
||||||
data []byte
|
t.Helper()
|
||||||
path string
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want []httpGroupTarget
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
|
|
||||||
{
|
result, err := parseAPIResponse([]byte(data), path)
|
||||||
name: "parse ok",
|
if err != nil {
|
||||||
args: args{
|
t.Fatalf("parseAPIResponse() error: %s", err)
|
||||||
path: "/ok",
|
}
|
||||||
data: []byte(`[
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%v\nwant\n%v", result, resultExpected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse ok
|
||||||
|
data := `[
|
||||||
{"targets": ["http://target-1:9100","http://target-2:9150"],
|
{"targets": ["http://target-1:9100","http://target-2:9150"],
|
||||||
"labels": {"label-1":"value-1"} }
|
"labels": {"label-1":"value-1"} }
|
||||||
]`),
|
]`
|
||||||
},
|
path := "/ok"
|
||||||
want: []httpGroupTarget{
|
resultExpected := []httpGroupTarget{
|
||||||
{
|
{
|
||||||
Labels: promutils.NewLabelsFromMap(map[string]string{"label-1": "value-1"}),
|
Labels: promutils.NewLabelsFromMap(map[string]string{"label-1": "value-1"}),
|
||||||
Targets: []string{"http://target-1:9100", "http://target-2:9150"},
|
Targets: []string{"http://target-1:9100", "http://target-2:9150"},
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, path, resultExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseAPIResponse(tt.args.data, tt.args.path)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseAPIResponse() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("parseAPIResponse() got = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,45 +7,34 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_addHTTPTargetLabels(t *testing.T) {
|
func TestAddHTTPTargetLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(src []httpGroupTarget, labelssExpected []*promutils.Labels) {
|
||||||
src []httpGroupTarget
|
t.Helper()
|
||||||
|
|
||||||
|
labelss := addHTTPTargetLabels(src, "http://foo.bar/baz?aaa=bb")
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// add ok
|
||||||
args args
|
src := []httpGroupTarget{
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "add ok",
|
Targets: []string{"127.0.0.1:9100", "127.0.0.2:91001"},
|
||||||
args: args{
|
Labels: promutils.NewLabelsFromMap(map[string]string{"__meta_kubernetes_pod": "pod-1", "__meta_consul_dc": "dc-2"}),
|
||||||
src: []httpGroupTarget{
|
|
||||||
{
|
|
||||||
Targets: []string{"127.0.0.1:9100", "127.0.0.2:91001"},
|
|
||||||
Labels: promutils.NewLabelsFromMap(map[string]string{"__meta_kubernetes_pod": "pod-1", "__meta_consul_dc": "dc-2"}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "127.0.0.1:9100",
|
|
||||||
"__meta_kubernetes_pod": "pod-1",
|
|
||||||
"__meta_consul_dc": "dc-2",
|
|
||||||
"__meta_url": "http://foo.bar/baz?aaa=bb",
|
|
||||||
}),
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "127.0.0.2:91001",
|
|
||||||
"__meta_kubernetes_pod": "pod-1",
|
|
||||||
"__meta_consul_dc": "dc-2",
|
|
||||||
"__meta_url": "http://foo.bar/baz?aaa=bb",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected := []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addHTTPTargetLabels(tt.args.src, "http://foo.bar/baz?aaa=bb")
|
"__address__": "127.0.0.1:9100",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_kubernetes_pod": "pod-1",
|
||||||
})
|
"__meta_consul_dc": "dc-2",
|
||||||
|
"__meta_url": "http://foo.bar/baz?aaa=bb",
|
||||||
|
}),
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "127.0.0.2:91001",
|
||||||
|
"__meta_kubernetes_pod": "pod-1",
|
||||||
|
"__meta_consul_dc": "dc-2",
|
||||||
|
"__meta_url": "http://foo.bar/baz?aaa=bb",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
f(src, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -936,9 +936,12 @@ func (uw *urlWatcher) maybeUpdateDependedScrapeWorksLocked() {
|
||||||
// Bookmark is a bookmark message from Kubernetes Watch API.
|
// Bookmark is a bookmark message from Kubernetes Watch API.
|
||||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#watch-bookmarks
|
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#watch-bookmarks
|
||||||
type Bookmark struct {
|
type Bookmark struct {
|
||||||
Metadata struct {
|
Metadata BookmarkMetadata
|
||||||
ResourceVersion string
|
}
|
||||||
}
|
|
||||||
|
// BookmarkMetadata is metadata for Bookmark
|
||||||
|
type BookmarkMetadata struct {
|
||||||
|
ResourceVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBookmark(data []byte) (*Bookmark, error) {
|
func parseBookmark(data []byte) (*Bookmark, error) {
|
||||||
|
|
|
@ -12,10 +12,10 @@ func TestParseEndpointSliceListFail(t *testing.T) {
|
||||||
r := bytes.NewBufferString(data)
|
r := bytes.NewBufferString(data)
|
||||||
objectsByKey, _, err := parseEndpointSliceList(r)
|
objectsByKey, _, err := parseEndpointSliceList(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("unexpected result, test must fail! data: %s", data)
|
t.Fatalf("unexpected result, test must fail! data: %s", data)
|
||||||
}
|
}
|
||||||
if len(objectsByKey) != 0 {
|
if len(objectsByKey) != 0 {
|
||||||
t.Errorf("EndpointSliceList must be emptry, got: %v", objectsByKey)
|
t.Fatalf("EndpointSliceList must be emptry, got: %v", objectsByKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,8 +156,7 @@ func TestParseEndpointSliceListSuccess(t *testing.T) {
|
||||||
r := bytes.NewBufferString(data)
|
r := bytes.NewBufferString(data)
|
||||||
objectsByKey, meta, err := parseEndpointSliceList(r)
|
objectsByKey, meta, err := parseEndpointSliceList(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot parse data for EndpointSliceList: %v", err)
|
t.Fatalf("cannot parse data for EndpointSliceList: %v", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
expectedResourceVersion := "1177"
|
expectedResourceVersion := "1177"
|
||||||
if meta.ResourceVersion != expectedResourceVersion {
|
if meta.ResourceVersion != expectedResourceVersion {
|
||||||
|
|
|
@ -20,21 +20,27 @@ type apiConfig struct {
|
||||||
// Config represent configuration file for kubernetes API server connection
|
// Config represent configuration file for kubernetes API server connection
|
||||||
// https://github.com/kubernetes/client-go/blob/master/tools/clientcmd/api/v1/types.go#L28
|
// https://github.com/kubernetes/client-go/blob/master/tools/clientcmd/api/v1/types.go#L28
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Kind string `yaml:"kind,omitempty"`
|
Kind string `yaml:"kind,omitempty"`
|
||||||
APIVersion string `yaml:"apiVersion,omitempty"`
|
APIVersion string `yaml:"apiVersion,omitempty"`
|
||||||
Clusters []struct {
|
Clusters []configCluster `yaml:"clusters"`
|
||||||
Name string `yaml:"name"`
|
AuthInfos []authInfo `yaml:"users"`
|
||||||
Cluster *Cluster `yaml:"cluster"`
|
Contexts []configContext `yaml:"contexts"`
|
||||||
} `yaml:"clusters"`
|
CurrentContext string `yaml:"current-context"`
|
||||||
AuthInfos []struct {
|
}
|
||||||
Name string `yaml:"name"`
|
|
||||||
AuthInfo *AuthInfo `yaml:"user"`
|
type configCluster struct {
|
||||||
} `yaml:"users"`
|
Name string `yaml:"name"`
|
||||||
Contexts []struct {
|
Cluster *Cluster `yaml:"cluster"`
|
||||||
Name string `yaml:"name"`
|
}
|
||||||
Context *Context `yaml:"context"`
|
|
||||||
} `yaml:"contexts"`
|
type authInfo struct {
|
||||||
CurrentContext string `yaml:"current-context"`
|
Name string `yaml:"name"`
|
||||||
|
AuthInfo *AuthInfo `yaml:"user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type configContext struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Context *Context `yaml:"context"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cluster contains information about how to communicate with a kubernetes cluster
|
// Cluster contains information about how to communicate with a kubernetes cluster
|
||||||
|
|
|
@ -264,18 +264,22 @@ type discoveryRequestNode struct {
|
||||||
// discoveryResponse represent xDS-requests for Kuma Service Mesh
|
// discoveryResponse represent xDS-requests for Kuma Service Mesh
|
||||||
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/discovery/v3/discovery.proto#envoy-v3-api-msg-service-discovery-v3-discoveryresponse
|
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/discovery/v3/discovery.proto#envoy-v3-api-msg-service-discovery-v3-discoveryresponse
|
||||||
type discoveryResponse struct {
|
type discoveryResponse struct {
|
||||||
VersionInfo string `json:"version_info"`
|
VersionInfo string `json:"version_info"`
|
||||||
Resources []struct {
|
Resources []resource `json:"resources"`
|
||||||
Mesh string `json:"mesh"`
|
Nonce string `json:"nonce"`
|
||||||
Service string `json:"service"`
|
}
|
||||||
Targets []struct {
|
|
||||||
Name string `json:"name"`
|
type resource struct {
|
||||||
Scheme string `json:"scheme"`
|
Mesh string `json:"mesh"`
|
||||||
Address string `json:"address"`
|
Service string `json:"service"`
|
||||||
MetricsPath string `json:"metrics_path"`
|
Targets []target `json:"targets"`
|
||||||
Labels map[string]string `json:"labels"`
|
Labels map[string]string `json:"labels"`
|
||||||
} `json:"targets"`
|
}
|
||||||
Labels map[string]string `json:"labels"`
|
|
||||||
} `json:"resources"`
|
type target struct {
|
||||||
Nonce string `json:"nonce"`
|
Name string `json:"name"`
|
||||||
|
Scheme string `json:"scheme"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
MetricsPath string `json:"metrics_path"`
|
||||||
|
Labels map[string]string `json:"labels"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,13 @@ func getServiceLabels(cfg *apiConfig) []*promutils.Labels {
|
||||||
// ServiceList is a list of Nomad services.
|
// ServiceList is a list of Nomad services.
|
||||||
// See https://developer.hashicorp.com/nomad/api-docs/services#list-services
|
// See https://developer.hashicorp.com/nomad/api-docs/services#list-services
|
||||||
type ServiceList struct {
|
type ServiceList struct {
|
||||||
Namespace string `json:"Namespace"`
|
Namespace string `json:"Namespace"`
|
||||||
Services []struct {
|
Services []service `json:"Services"`
|
||||||
ServiceName string `json:"ServiceName"`
|
}
|
||||||
Tags []string `json:"Tags"`
|
|
||||||
} `json:"Services"`
|
type service struct {
|
||||||
|
ServiceName string `json:"ServiceName"`
|
||||||
|
Tags []string `json:"Tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service is Nomad service.
|
// Service is Nomad service.
|
||||||
|
|
|
@ -14,10 +14,12 @@ import (
|
||||||
//
|
//
|
||||||
// See https://docs.openstack.org/api-ref/identity/v3/#authentication-and-token-management
|
// See https://docs.openstack.org/api-ref/identity/v3/#authentication-and-token-management
|
||||||
type authResponse struct {
|
type authResponse struct {
|
||||||
Token struct {
|
Token authToken
|
||||||
ExpiresAt time.Time `json:"expires_at,omitempty"`
|
}
|
||||||
Catalog []catalogItem `json:"catalog,omitempty"`
|
|
||||||
}
|
type authToken struct {
|
||||||
|
ExpiresAt time.Time `json:"expires_at,omitempty"`
|
||||||
|
Catalog []catalogItem `json:"catalog,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type catalogItem struct {
|
type catalogItem struct {
|
||||||
|
|
|
@ -1,124 +1,104 @@
|
||||||
package openstack
|
package openstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_buildAuthRequestBody1(t *testing.T) {
|
func TestBuildAuthRequestBody_Failure(t *testing.T) {
|
||||||
type args struct {
|
f := func(sdc *SDConfig) {
|
||||||
sdc *SDConfig
|
t.Helper()
|
||||||
}
|
|
||||||
tests := []struct {
|
_, err := buildAuthRequestBody(sdc)
|
||||||
name string
|
if err == nil {
|
||||||
args args
|
t.Fatalf("expecting non-nil error")
|
||||||
want []byte
|
}
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "empty config",
|
|
||||||
args: args{
|
|
||||||
sdc: &SDConfig{},
|
|
||||||
},
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "username password auth with domain",
|
|
||||||
args: args{
|
|
||||||
sdc: &SDConfig{
|
|
||||||
Username: "some-user",
|
|
||||||
Password: promauth.NewSecret("some-password"),
|
|
||||||
DomainName: "some-domain",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []byte(`{"auth":{"identity":{"methods":["password"],"password":{"user":{"name":"some-user","password":"some-password","domain":{"name":"some-domain"}}}},"scope":{"domain":{"name":"some-domain"}}}}`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "application credentials auth",
|
|
||||||
args: args{
|
|
||||||
sdc: &SDConfig{
|
|
||||||
ApplicationCredentialID: "some-id",
|
|
||||||
ApplicationCredentialSecret: promauth.NewSecret("some-secret"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []byte(`{"auth":{"identity":{"methods":["application_credential"],"application_credential":{"id":"some-id","secret":"some-secret"}}}}`),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := buildAuthRequestBody(tt.args.sdc)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("buildAuthRequestBody() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("buildAuthRequestBody() got = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// empty config
|
||||||
|
f(&SDConfig{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_getComputeEndpointURL1(t *testing.T) {
|
func TestBuildAuthRequestBody_Success(t *testing.T) {
|
||||||
type args struct {
|
f := func(sdc *SDConfig, resultExpected string) {
|
||||||
catalog []catalogItem
|
t.Helper()
|
||||||
availability string
|
|
||||||
region string
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "bad catalog data",
|
|
||||||
args: args{
|
|
||||||
catalog: []catalogItem{
|
|
||||||
{
|
|
||||||
Type: "keystone",
|
|
||||||
Endpoints: []endpoint{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "good private url",
|
|
||||||
args: args{
|
|
||||||
availability: "private",
|
|
||||||
catalog: []catalogItem{
|
|
||||||
{
|
|
||||||
Type: "compute",
|
|
||||||
Endpoints: []endpoint{
|
|
||||||
{
|
|
||||||
Interface: "private",
|
|
||||||
Type: "compute",
|
|
||||||
URL: "https://compute.test.local:8083/v2.1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: "keystone",
|
|
||||||
Endpoints: []endpoint{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: "https://compute.test.local:8083/v2.1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := getComputeEndpointURL(tt.args.catalog, tt.args.availability, tt.args.region)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("getComputeEndpointURL() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tt.wantErr && !reflect.DeepEqual(got.String(), tt.want) {
|
result, err := buildAuthRequestBody(sdc)
|
||||||
t.Errorf("getComputeEndpointURL() got = %v, want %v", got.String(), tt.want)
|
if err != nil {
|
||||||
}
|
t.Fatalf("buildAuthRequestBody() error: %s", err)
|
||||||
})
|
}
|
||||||
|
if string(result) != resultExpected {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%s\nwant\n%s", result, resultExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// username password auth with domain
|
||||||
|
f(&SDConfig{
|
||||||
|
Username: "some-user",
|
||||||
|
Password: promauth.NewSecret("some-password"),
|
||||||
|
DomainName: "some-domain",
|
||||||
|
}, `{"auth":{"identity":{"methods":["password"],"password":{"user":{"name":"some-user","password":"some-password","domain":{"name":"some-domain"}}}},"scope":{"domain":{"name":"some-domain"}}}}`)
|
||||||
|
|
||||||
|
// application credentials auth
|
||||||
|
f(&SDConfig{
|
||||||
|
ApplicationCredentialID: "some-id",
|
||||||
|
ApplicationCredentialSecret: promauth.NewSecret("some-secret"),
|
||||||
|
}, `{"auth":{"identity":{"methods":["application_credential"],"application_credential":{"id":"some-id","secret":"some-secret"}}}}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetComputeEndpointURL_Failure(t *testing.T) {
|
||||||
|
f := func(catalog []catalogItem) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
_, err := getComputeEndpointURL(catalog, "", "")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expecting non-nil error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bad catalog data
|
||||||
|
catalog := []catalogItem{
|
||||||
|
{
|
||||||
|
Type: "keystone",
|
||||||
|
Endpoints: []endpoint{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
f(catalog)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetComputeEndpointURL_Success(t *testing.T) {
|
||||||
|
f := func(catalog []catalogItem, availability, region, resultExpected string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
resultURL, err := getComputeEndpointURL(catalog, availability, region)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("getComputeEndpointURL() error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resultURL.String() != resultExpected {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%s\nwant\n%s", resultURL, resultExpected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// good private url
|
||||||
|
catalog := []catalogItem{
|
||||||
|
{
|
||||||
|
Type: "compute",
|
||||||
|
Endpoints: []endpoint{
|
||||||
|
{
|
||||||
|
Interface: "private",
|
||||||
|
Type: "compute",
|
||||||
|
URL: "https://compute.test.local:8083/v2.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: "keystone",
|
||||||
|
Endpoints: []endpoint{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
availability := "private"
|
||||||
|
resultExpected := "https://compute.test.local:8083/v2.1"
|
||||||
|
f(catalog, availability, "", resultExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,13 @@ import (
|
||||||
|
|
||||||
// See https://docs.openstack.org/api-ref/compute/#list-hypervisors-details
|
// See https://docs.openstack.org/api-ref/compute/#list-hypervisors-details
|
||||||
type hypervisorDetail struct {
|
type hypervisorDetail struct {
|
||||||
Hypervisors []hypervisor `json:"hypervisors"`
|
Hypervisors []hypervisor `json:"hypervisors"`
|
||||||
Links []struct {
|
Links []hypervisorLink `json:"hypervisors_links,omitempty"`
|
||||||
HREF string `json:"href"`
|
}
|
||||||
Rel string `json:"rel,omitempty"`
|
|
||||||
} `json:"hypervisors_links,omitempty"`
|
type hypervisorLink struct {
|
||||||
|
HREF string `json:"href"`
|
||||||
|
Rel string `json:"rel,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type hypervisor struct {
|
type hypervisor struct {
|
||||||
|
|
|
@ -8,27 +8,35 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseHypervisorDetail(t *testing.T) {
|
func TestParseHypervisorDetail_Failure(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
_, err := parseHypervisorDetail([]byte(data))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expecting non-nil error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// bad data
|
||||||
args args
|
f(`{ff}`)
|
||||||
want hypervisorDetail
|
}
|
||||||
wantErr bool
|
|
||||||
}{
|
func TestParseHypervisorDetail_Success(t *testing.T) {
|
||||||
{
|
f := func(data string, resultExpected *hypervisorDetail) {
|
||||||
name: "bad data",
|
t.Helper()
|
||||||
args: args{
|
|
||||||
data: []byte(`{ff}`),
|
result, err := parseHypervisorDetail([]byte(data))
|
||||||
},
|
if err != nil {
|
||||||
wantErr: true,
|
t.Fatalf("parseHypervisorDetail() error: %s", err)
|
||||||
},
|
}
|
||||||
{
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
name: "1 hypervisor",
|
t.Fatalf("unexpected result\ngot\n%#v\nwant\n%#v", result, resultExpected)
|
||||||
args: args{
|
}
|
||||||
data: []byte(`{
|
}
|
||||||
|
|
||||||
|
// 1 hypervisor
|
||||||
|
data := `{
|
||||||
"hypervisors": [
|
"hypervisors": [
|
||||||
{
|
{
|
||||||
"cpu_info": {
|
"cpu_info": {
|
||||||
|
@ -69,78 +77,51 @@ func Test_parseHypervisorDetail(t *testing.T) {
|
||||||
"vcpus": 2,
|
"vcpus": 2,
|
||||||
"vcpus_used": 0
|
"vcpus_used": 0
|
||||||
}
|
}
|
||||||
]}`),
|
]}`
|
||||||
},
|
|
||||||
want: hypervisorDetail{
|
resultExpected := &hypervisorDetail{
|
||||||
Hypervisors: []hypervisor{
|
Hypervisors: []hypervisor{
|
||||||
{
|
{
|
||||||
HostIP: "1.1.1.1",
|
HostIP: "1.1.1.1",
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Hostname: "host1",
|
Hostname: "host1",
|
||||||
Status: "enabled",
|
Status: "enabled",
|
||||||
State: "up",
|
State: "up",
|
||||||
Type: "fake",
|
Type: "fake",
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, resultExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseHypervisorDetail(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseHypervisorDetail() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !tt.wantErr && !reflect.DeepEqual(*got, tt.want) {
|
|
||||||
t.Errorf("parseHypervisorDetail() got = %v, want %v", *got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_addHypervisorLabels(t *testing.T) {
|
func TestAddHypervisorLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(hvs []hypervisor, labelssExpected []*promutils.Labels) {
|
||||||
hvs []hypervisor
|
t.Helper()
|
||||||
port int
|
|
||||||
|
labelss := addHypervisorLabels(hvs, 9100)
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
hvs := []hypervisor{
|
||||||
args args
|
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "",
|
Type: "fake",
|
||||||
args: args{
|
ID: 5,
|
||||||
port: 9100,
|
State: "enabled",
|
||||||
hvs: []hypervisor{
|
Status: "up",
|
||||||
{
|
Hostname: "fakehost",
|
||||||
Type: "fake",
|
HostIP: "1.2.2.2",
|
||||||
ID: 5,
|
|
||||||
State: "enabled",
|
|
||||||
Status: "up",
|
|
||||||
Hostname: "fakehost",
|
|
||||||
HostIP: "1.2.2.2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "1.2.2.2:9100",
|
|
||||||
"__meta_openstack_hypervisor_host_ip": "1.2.2.2",
|
|
||||||
"__meta_openstack_hypervisor_hostname": "fakehost",
|
|
||||||
"__meta_openstack_hypervisor_id": "5",
|
|
||||||
"__meta_openstack_hypervisor_state": "enabled",
|
|
||||||
"__meta_openstack_hypervisor_status": "up",
|
|
||||||
"__meta_openstack_hypervisor_type": "fake",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected := []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addHypervisorLabels(tt.args.hvs, tt.args.port)
|
"__address__": "1.2.2.2:9100",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_openstack_hypervisor_host_ip": "1.2.2.2",
|
||||||
})
|
"__meta_openstack_hypervisor_hostname": "fakehost",
|
||||||
|
"__meta_openstack_hypervisor_id": "5",
|
||||||
|
"__meta_openstack_hypervisor_state": "enabled",
|
||||||
|
"__meta_openstack_hypervisor_status": "up",
|
||||||
|
"__meta_openstack_hypervisor_type": "fake",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
f(hvs, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,28 +14,34 @@ import (
|
||||||
// See https://docs.openstack.org/api-ref/compute/#list-servers
|
// See https://docs.openstack.org/api-ref/compute/#list-servers
|
||||||
type serversDetail struct {
|
type serversDetail struct {
|
||||||
Servers []server `json:"servers"`
|
Servers []server `json:"servers"`
|
||||||
Links []struct {
|
Links []link `json:"servers_links,omitempty"`
|
||||||
HREF string `json:"href"`
|
}
|
||||||
Rel string `json:"rel"`
|
|
||||||
} `json:"servers_links,omitempty"`
|
type link struct {
|
||||||
|
HREF string `json:"href"`
|
||||||
|
Rel string `json:"rel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
TenantID string `json:"tenant_id"`
|
TenantID string `json:"tenant_id"`
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
HostID string `json:"hostid"`
|
HostID string `json:"hostid"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Addresses map[string][]struct {
|
Addresses map[string][]serverAddress `json:"addresses"`
|
||||||
Address string `json:"addr"`
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
Version int `json:"version"`
|
Flavor serverFlavor `json:"flavor"`
|
||||||
Type string `json:"OS-EXT-IPS:type"`
|
}
|
||||||
} `json:"addresses"`
|
|
||||||
Metadata map[string]string `json:"metadata,omitempty"`
|
type serverAddress struct {
|
||||||
Flavor struct {
|
Address string `json:"addr"`
|
||||||
ID string `json:"id"`
|
Version int `json:"version"`
|
||||||
} `json:"flavor"`
|
Type string `json:"OS-EXT-IPS:type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverFlavor struct {
|
||||||
|
ID string `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseServersDetail(data []byte) (*serversDetail, error) {
|
func parseServersDetail(data []byte) (*serversDetail, error) {
|
||||||
|
|
|
@ -8,159 +8,133 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_addInstanceLabels(t *testing.T) {
|
func TestAddInstanceLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(servers []server, labelssExpected []*promutils.Labels) {
|
||||||
servers []server
|
t.Helper()
|
||||||
port int
|
|
||||||
|
labelss := addInstanceLabels(servers, 9100)
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// empty response
|
||||||
args args
|
f(nil, nil)
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
// one server
|
||||||
|
servers := []server{
|
||||||
{
|
{
|
||||||
name: "empty_response",
|
ID: "10",
|
||||||
args: args{
|
Status: "enabled",
|
||||||
port: 9100,
|
Name: "server-1",
|
||||||
|
HostID: "some-host-id",
|
||||||
|
TenantID: "some-tenant-id",
|
||||||
|
UserID: "some-user-id",
|
||||||
|
Flavor: serverFlavor{
|
||||||
|
ID: "5",
|
||||||
},
|
},
|
||||||
},
|
Addresses: map[string][]serverAddress{
|
||||||
{
|
"test": {
|
||||||
name: "one_server",
|
|
||||||
args: args{
|
|
||||||
port: 9100,
|
|
||||||
servers: []server{
|
|
||||||
{
|
{
|
||||||
ID: "10",
|
Address: "192.168.0.1",
|
||||||
Status: "enabled",
|
Version: 4,
|
||||||
Name: "server-1",
|
Type: "fixed",
|
||||||
HostID: "some-host-id",
|
|
||||||
TenantID: "some-tenant-id",
|
|
||||||
UserID: "some-user-id",
|
|
||||||
Flavor: struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
}{ID: "5"},
|
|
||||||
Addresses: map[string][]struct {
|
|
||||||
Address string `json:"addr"`
|
|
||||||
Version int `json:"version"`
|
|
||||||
Type string `json:"OS-EXT-IPS:type"`
|
|
||||||
}{
|
|
||||||
"test": {
|
|
||||||
{
|
|
||||||
Address: "192.168.0.1",
|
|
||||||
Version: 4,
|
|
||||||
Type: "fixed",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "192.168.0.1:9100",
|
|
||||||
"__meta_openstack_address_pool": "test",
|
|
||||||
"__meta_openstack_instance_flavor": "5",
|
|
||||||
"__meta_openstack_instance_id": "10",
|
|
||||||
"__meta_openstack_instance_name": "server-1",
|
|
||||||
"__meta_openstack_instance_status": "enabled",
|
|
||||||
"__meta_openstack_private_ip": "192.168.0.1",
|
|
||||||
"__meta_openstack_project_id": "some-tenant-id",
|
|
||||||
"__meta_openstack_user_id": "some-user-id",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
labelssExpected := []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "192.168.0.1:9100",
|
||||||
|
"__meta_openstack_address_pool": "test",
|
||||||
|
"__meta_openstack_instance_flavor": "5",
|
||||||
|
"__meta_openstack_instance_id": "10",
|
||||||
|
"__meta_openstack_instance_name": "server-1",
|
||||||
|
"__meta_openstack_instance_status": "enabled",
|
||||||
|
"__meta_openstack_private_ip": "192.168.0.1",
|
||||||
|
"__meta_openstack_project_id": "some-tenant-id",
|
||||||
|
"__meta_openstack_user_id": "some-user-id",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(servers, labelssExpected)
|
||||||
|
|
||||||
|
// with public ip
|
||||||
|
servers = []server{
|
||||||
{
|
{
|
||||||
name: "with_public_ip",
|
ID: "10",
|
||||||
args: args{
|
Status: "enabled",
|
||||||
port: 9100,
|
Name: "server-2",
|
||||||
servers: []server{
|
HostID: "some-host-id",
|
||||||
|
TenantID: "some-tenant-id",
|
||||||
|
UserID: "some-user-id",
|
||||||
|
Flavor: serverFlavor{
|
||||||
|
ID: "5",
|
||||||
|
},
|
||||||
|
Addresses: map[string][]serverAddress{
|
||||||
|
"test": {
|
||||||
{
|
{
|
||||||
ID: "10",
|
Address: "192.168.0.1",
|
||||||
Status: "enabled",
|
Version: 4,
|
||||||
Name: "server-2",
|
Type: "fixed",
|
||||||
HostID: "some-host-id",
|
},
|
||||||
TenantID: "some-tenant-id",
|
{
|
||||||
UserID: "some-user-id",
|
Address: "1.5.5.5",
|
||||||
Flavor: struct {
|
Version: 4,
|
||||||
ID string `json:"id"`
|
Type: "floating",
|
||||||
}{ID: "5"},
|
},
|
||||||
Addresses: map[string][]struct {
|
},
|
||||||
Address string `json:"addr"`
|
"internal": {
|
||||||
Version int `json:"version"`
|
{
|
||||||
Type string `json:"OS-EXT-IPS:type"`
|
Address: "10.10.0.1",
|
||||||
}{
|
Version: 4,
|
||||||
"test": {
|
Type: "fixed",
|
||||||
{
|
|
||||||
Address: "192.168.0.1",
|
|
||||||
Version: 4,
|
|
||||||
Type: "fixed",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: "1.5.5.5",
|
|
||||||
Version: 4,
|
|
||||||
Type: "floating",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"internal": {
|
|
||||||
{
|
|
||||||
Address: "10.10.0.1",
|
|
||||||
Version: 4,
|
|
||||||
Type: "fixed",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "10.10.0.1:9100",
|
|
||||||
"__meta_openstack_address_pool": "internal",
|
|
||||||
"__meta_openstack_instance_flavor": "5",
|
|
||||||
"__meta_openstack_instance_id": "10",
|
|
||||||
"__meta_openstack_instance_name": "server-2",
|
|
||||||
"__meta_openstack_instance_status": "enabled",
|
|
||||||
"__meta_openstack_private_ip": "10.10.0.1",
|
|
||||||
"__meta_openstack_project_id": "some-tenant-id",
|
|
||||||
"__meta_openstack_user_id": "some-user-id",
|
|
||||||
}),
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "192.168.0.1:9100",
|
|
||||||
"__meta_openstack_address_pool": "test",
|
|
||||||
"__meta_openstack_instance_flavor": "5",
|
|
||||||
"__meta_openstack_instance_id": "10",
|
|
||||||
"__meta_openstack_instance_name": "server-2",
|
|
||||||
"__meta_openstack_instance_status": "enabled",
|
|
||||||
"__meta_openstack_private_ip": "192.168.0.1",
|
|
||||||
"__meta_openstack_public_ip": "1.5.5.5",
|
|
||||||
"__meta_openstack_project_id": "some-tenant-id",
|
|
||||||
"__meta_openstack_user_id": "some-user-id",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected = []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addInstanceLabels(tt.args.servers, tt.args.port)
|
"__address__": "10.10.0.1:9100",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_openstack_address_pool": "internal",
|
||||||
})
|
"__meta_openstack_instance_flavor": "5",
|
||||||
|
"__meta_openstack_instance_id": "10",
|
||||||
|
"__meta_openstack_instance_name": "server-2",
|
||||||
|
"__meta_openstack_instance_status": "enabled",
|
||||||
|
"__meta_openstack_private_ip": "10.10.0.1",
|
||||||
|
"__meta_openstack_project_id": "some-tenant-id",
|
||||||
|
"__meta_openstack_user_id": "some-user-id",
|
||||||
|
}),
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "192.168.0.1:9100",
|
||||||
|
"__meta_openstack_address_pool": "test",
|
||||||
|
"__meta_openstack_instance_flavor": "5",
|
||||||
|
"__meta_openstack_instance_id": "10",
|
||||||
|
"__meta_openstack_instance_name": "server-2",
|
||||||
|
"__meta_openstack_instance_status": "enabled",
|
||||||
|
"__meta_openstack_private_ip": "192.168.0.1",
|
||||||
|
"__meta_openstack_public_ip": "1.5.5.5",
|
||||||
|
"__meta_openstack_project_id": "some-tenant-id",
|
||||||
|
"__meta_openstack_user_id": "some-user-id",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
f(servers, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_parseServersDetail(t *testing.T) {
|
func TestParseServersDetail(t *testing.T) {
|
||||||
type args struct {
|
f := func(data string, resultExpected *serversDetail) {
|
||||||
data []byte
|
t.Helper()
|
||||||
|
|
||||||
|
result, err := parseServersDetail([]byte(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseServersDetail() error: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(result, resultExpected) {
|
||||||
|
t.Fatalf("unexpected result\ngot\n%v\nwant\n%v", result, resultExpected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// parse ok
|
||||||
args args
|
data := `{
|
||||||
want serversDetail
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "parse ok",
|
|
||||||
args: args{
|
|
||||||
data: []byte(`{
|
|
||||||
"servers":[
|
"servers":[
|
||||||
{
|
{
|
||||||
"id":"c9f68076-01a3-489a-aebe-8b773c71e7f3",
|
"id":"c9f68076-01a3-489a-aebe-8b773c71e7f3",
|
||||||
|
@ -210,54 +184,36 @@ func Test_parseServersDetail(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`),
|
}`
|
||||||
},
|
resultExpected := &serversDetail{
|
||||||
want: serversDetail{
|
Servers: []server{
|
||||||
Servers: []server{
|
{
|
||||||
{
|
Flavor: serverFlavor{
|
||||||
Flavor: struct {
|
ID: "1",
|
||||||
ID string `json:"id"`
|
},
|
||||||
}{ID: "1"},
|
ID: "c9f68076-01a3-489a-aebe-8b773c71e7f3",
|
||||||
ID: "c9f68076-01a3-489a-aebe-8b773c71e7f3",
|
TenantID: "d34be4e44f9c444eab9a5ec7b953951f",
|
||||||
TenantID: "d34be4e44f9c444eab9a5ec7b953951f",
|
UserID: "e55737f142ac42f18093037760656bd7",
|
||||||
UserID: "e55737f142ac42f18093037760656bd7",
|
Name: "test10",
|
||||||
Name: "test10",
|
HostID: "e26db8db23736877aa92ebbbe11743b2a2a3b107aada00a8a0cf474b",
|
||||||
HostID: "e26db8db23736877aa92ebbbe11743b2a2a3b107aada00a8a0cf474b",
|
Status: "ACTIVE",
|
||||||
Status: "ACTIVE",
|
Metadata: map[string]string{},
|
||||||
Metadata: map[string]string{},
|
Addresses: map[string][]serverAddress{
|
||||||
Addresses: map[string][]struct {
|
"test": {
|
||||||
Address string `json:"addr"`
|
{
|
||||||
Version int `json:"version"`
|
Address: "192.168.222.15",
|
||||||
Type string `json:"OS-EXT-IPS:type"`
|
Version: 4,
|
||||||
}{
|
Type: "fixed",
|
||||||
"test": {
|
},
|
||||||
{
|
{
|
||||||
Address: "192.168.222.15",
|
Address: "10.20.20.69",
|
||||||
Version: 4,
|
Version: 4,
|
||||||
Type: "fixed",
|
Type: "floating",
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: "10.20.20.69",
|
|
||||||
Version: 4,
|
|
||||||
Type: "floating",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
f(data, resultExpected)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := parseServersDetail(tt.args.data)
|
|
||||||
if (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("parseServersDetail() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !tt.wantErr && !reflect.DeepEqual(*got, tt.want) {
|
|
||||||
t.Errorf("parseServersDetail() \ngot = %v,\nwant= %v", *got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,169 +7,157 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_addInstanceLabels(t *testing.T) {
|
func TestAddInstanceLabels(t *testing.T) {
|
||||||
type args struct {
|
f := func(instances []instance, labelssExpected []*promutils.Labels) {
|
||||||
instances []instance
|
t.Helper()
|
||||||
|
|
||||||
|
labelss := addInstanceLabels(instances)
|
||||||
|
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
|
||||||
name string
|
// empty response
|
||||||
args args
|
f(nil, nil)
|
||||||
want []*promutils.Labels
|
|
||||||
}{
|
// one server
|
||||||
|
instances := []instance{
|
||||||
{
|
{
|
||||||
name: "empty_response",
|
Name: "server-1",
|
||||||
args: args{},
|
ID: "test",
|
||||||
|
FQDN: "server-1.ru-central1.internal",
|
||||||
|
FolderID: "test",
|
||||||
|
Status: "RUNNING",
|
||||||
|
PlatformID: "s2.micro",
|
||||||
|
Resources: resources{
|
||||||
|
Cores: "2",
|
||||||
|
CoreFraction: "20",
|
||||||
|
Memory: "4",
|
||||||
|
},
|
||||||
|
NetworkInterfaces: []networkInterface{
|
||||||
|
{
|
||||||
|
Index: "0",
|
||||||
|
PrimaryV4Address: primaryV4Address{
|
||||||
|
Address: "192.168.1.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
labelssExpected := []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "server-1.ru-central1.internal",
|
||||||
|
"__meta_yandexcloud_instance_name": "server-1",
|
||||||
|
"__meta_yandexcloud_instance_fqdn": "server-1.ru-central1.internal",
|
||||||
|
"__meta_yandexcloud_instance_id": "test",
|
||||||
|
"__meta_yandexcloud_instance_status": "RUNNING",
|
||||||
|
"__meta_yandexcloud_instance_platform_id": "s2.micro",
|
||||||
|
"__meta_yandexcloud_instance_resources_cores": "2",
|
||||||
|
"__meta_yandexcloud_instance_resources_core_fraction": "20",
|
||||||
|
"__meta_yandexcloud_instance_resources_memory": "4",
|
||||||
|
"__meta_yandexcloud_folder_id": "test",
|
||||||
|
"__meta_yandexcloud_instance_private_ip_0": "192.168.1.1",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(instances, labelssExpected)
|
||||||
|
|
||||||
|
// with public ip
|
||||||
|
instances = []instance{
|
||||||
{
|
{
|
||||||
name: "one_server",
|
Name: "server-1",
|
||||||
args: args{
|
ID: "test",
|
||||||
instances: []instance{
|
FQDN: "server-1.ru-central1.internal",
|
||||||
{
|
FolderID: "test",
|
||||||
Name: "server-1",
|
Status: "RUNNING",
|
||||||
ID: "test",
|
PlatformID: "s2.micro",
|
||||||
FQDN: "server-1.ru-central1.internal",
|
Resources: resources{
|
||||||
FolderID: "test",
|
Cores: "2",
|
||||||
Status: "RUNNING",
|
CoreFraction: "20",
|
||||||
PlatformID: "s2.micro",
|
Memory: "4",
|
||||||
Resources: resources{
|
},
|
||||||
Cores: "2",
|
NetworkInterfaces: []networkInterface{
|
||||||
CoreFraction: "20",
|
{
|
||||||
Memory: "4",
|
Index: "0",
|
||||||
|
PrimaryV4Address: primaryV4Address{
|
||||||
|
Address: "192.168.1.1",
|
||||||
|
OneToOneNat: oneToOneNat{
|
||||||
|
Address: "1.1.1.1",
|
||||||
},
|
},
|
||||||
NetworkInterfaces: []networkInterface{
|
},
|
||||||
{
|
},
|
||||||
Index: "0",
|
},
|
||||||
PrimaryV4Address: primaryV4Address{
|
},
|
||||||
Address: "192.168.1.1",
|
}
|
||||||
|
labelssExpected = []*promutils.Labels{
|
||||||
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
|
"__address__": "server-1.ru-central1.internal",
|
||||||
|
"__meta_yandexcloud_instance_fqdn": "server-1.ru-central1.internal",
|
||||||
|
"__meta_yandexcloud_instance_name": "server-1",
|
||||||
|
"__meta_yandexcloud_instance_id": "test",
|
||||||
|
"__meta_yandexcloud_instance_status": "RUNNING",
|
||||||
|
"__meta_yandexcloud_instance_platform_id": "s2.micro",
|
||||||
|
"__meta_yandexcloud_instance_resources_cores": "2",
|
||||||
|
"__meta_yandexcloud_instance_resources_core_fraction": "20",
|
||||||
|
"__meta_yandexcloud_instance_resources_memory": "4",
|
||||||
|
"__meta_yandexcloud_folder_id": "test",
|
||||||
|
"__meta_yandexcloud_instance_private_ip_0": "192.168.1.1",
|
||||||
|
"__meta_yandexcloud_instance_public_ip_0": "1.1.1.1",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
f(instances, labelssExpected)
|
||||||
|
|
||||||
|
// with dns record
|
||||||
|
instances = []instance{
|
||||||
|
{
|
||||||
|
Name: "server-1",
|
||||||
|
ID: "test",
|
||||||
|
FQDN: "server-1.ru-central1.internal",
|
||||||
|
FolderID: "test",
|
||||||
|
Status: "RUNNING",
|
||||||
|
PlatformID: "s2.micro",
|
||||||
|
Resources: resources{
|
||||||
|
Cores: "2",
|
||||||
|
CoreFraction: "20",
|
||||||
|
Memory: "4",
|
||||||
|
},
|
||||||
|
NetworkInterfaces: []networkInterface{
|
||||||
|
{
|
||||||
|
Index: "0",
|
||||||
|
PrimaryV4Address: primaryV4Address{
|
||||||
|
Address: "192.168.1.1",
|
||||||
|
OneToOneNat: oneToOneNat{
|
||||||
|
Address: "1.1.1.1",
|
||||||
|
DNSRecords: []dnsRecord{
|
||||||
|
{
|
||||||
|
FQDN: "server-1.example.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DNSRecords: []dnsRecord{
|
||||||
|
{
|
||||||
|
FQDN: "server-1.example.local",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "server-1.ru-central1.internal",
|
|
||||||
"__meta_yandexcloud_instance_name": "server-1",
|
|
||||||
"__meta_yandexcloud_instance_fqdn": "server-1.ru-central1.internal",
|
|
||||||
"__meta_yandexcloud_instance_id": "test",
|
|
||||||
"__meta_yandexcloud_instance_status": "RUNNING",
|
|
||||||
"__meta_yandexcloud_instance_platform_id": "s2.micro",
|
|
||||||
"__meta_yandexcloud_instance_resources_cores": "2",
|
|
||||||
"__meta_yandexcloud_instance_resources_core_fraction": "20",
|
|
||||||
"__meta_yandexcloud_instance_resources_memory": "4",
|
|
||||||
"__meta_yandexcloud_folder_id": "test",
|
|
||||||
"__meta_yandexcloud_instance_private_ip_0": "192.168.1.1",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with_public_ip",
|
|
||||||
args: args{
|
|
||||||
instances: []instance{
|
|
||||||
{
|
|
||||||
Name: "server-1",
|
|
||||||
ID: "test",
|
|
||||||
FQDN: "server-1.ru-central1.internal",
|
|
||||||
FolderID: "test",
|
|
||||||
Status: "RUNNING",
|
|
||||||
PlatformID: "s2.micro",
|
|
||||||
Resources: resources{
|
|
||||||
Cores: "2",
|
|
||||||
CoreFraction: "20",
|
|
||||||
Memory: "4",
|
|
||||||
},
|
|
||||||
NetworkInterfaces: []networkInterface{
|
|
||||||
{
|
|
||||||
Index: "0",
|
|
||||||
PrimaryV4Address: primaryV4Address{
|
|
||||||
Address: "192.168.1.1",
|
|
||||||
OneToOneNat: oneToOneNat{
|
|
||||||
Address: "1.1.1.1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "server-1.ru-central1.internal",
|
|
||||||
"__meta_yandexcloud_instance_fqdn": "server-1.ru-central1.internal",
|
|
||||||
"__meta_yandexcloud_instance_name": "server-1",
|
|
||||||
"__meta_yandexcloud_instance_id": "test",
|
|
||||||
"__meta_yandexcloud_instance_status": "RUNNING",
|
|
||||||
"__meta_yandexcloud_instance_platform_id": "s2.micro",
|
|
||||||
"__meta_yandexcloud_instance_resources_cores": "2",
|
|
||||||
"__meta_yandexcloud_instance_resources_core_fraction": "20",
|
|
||||||
"__meta_yandexcloud_instance_resources_memory": "4",
|
|
||||||
"__meta_yandexcloud_folder_id": "test",
|
|
||||||
"__meta_yandexcloud_instance_private_ip_0": "192.168.1.1",
|
|
||||||
"__meta_yandexcloud_instance_public_ip_0": "1.1.1.1",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with_dns_record",
|
|
||||||
args: args{
|
|
||||||
instances: []instance{
|
|
||||||
{
|
|
||||||
Name: "server-1",
|
|
||||||
ID: "test",
|
|
||||||
FQDN: "server-1.ru-central1.internal",
|
|
||||||
FolderID: "test",
|
|
||||||
Status: "RUNNING",
|
|
||||||
PlatformID: "s2.micro",
|
|
||||||
Resources: resources{
|
|
||||||
Cores: "2",
|
|
||||||
CoreFraction: "20",
|
|
||||||
Memory: "4",
|
|
||||||
},
|
|
||||||
NetworkInterfaces: []networkInterface{
|
|
||||||
{
|
|
||||||
Index: "0",
|
|
||||||
PrimaryV4Address: primaryV4Address{
|
|
||||||
Address: "192.168.1.1",
|
|
||||||
OneToOneNat: oneToOneNat{
|
|
||||||
Address: "1.1.1.1",
|
|
||||||
DNSRecords: []dnsRecord{
|
|
||||||
{FQDN: "server-1.example.com"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
DNSRecords: []dnsRecord{
|
|
||||||
{FQDN: "server-1.example.local"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: []*promutils.Labels{
|
|
||||||
promutils.NewLabelsFromMap(map[string]string{
|
|
||||||
"__address__": "server-1.ru-central1.internal",
|
|
||||||
"__meta_yandexcloud_instance_name": "server-1",
|
|
||||||
"__meta_yandexcloud_instance_fqdn": "server-1.ru-central1.internal",
|
|
||||||
"__meta_yandexcloud_instance_id": "test",
|
|
||||||
"__meta_yandexcloud_instance_status": "RUNNING",
|
|
||||||
"__meta_yandexcloud_instance_platform_id": "s2.micro",
|
|
||||||
"__meta_yandexcloud_instance_resources_cores": "2",
|
|
||||||
"__meta_yandexcloud_instance_resources_core_fraction": "20",
|
|
||||||
"__meta_yandexcloud_instance_resources_memory": "4",
|
|
||||||
"__meta_yandexcloud_folder_id": "test",
|
|
||||||
"__meta_yandexcloud_instance_private_ip_0": "192.168.1.1",
|
|
||||||
"__meta_yandexcloud_instance_public_ip_0": "1.1.1.1",
|
|
||||||
"__meta_yandexcloud_instance_private_dns_0": "server-1.example.local",
|
|
||||||
"__meta_yandexcloud_instance_public_dns_0": "server-1.example.com",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
labelssExpected = []*promutils.Labels{
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
promutils.NewLabelsFromMap(map[string]string{
|
||||||
got := addInstanceLabels(tt.args.instances)
|
"__address__": "server-1.ru-central1.internal",
|
||||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
"__meta_yandexcloud_instance_name": "server-1",
|
||||||
})
|
"__meta_yandexcloud_instance_fqdn": "server-1.ru-central1.internal",
|
||||||
|
"__meta_yandexcloud_instance_id": "test",
|
||||||
|
"__meta_yandexcloud_instance_status": "RUNNING",
|
||||||
|
"__meta_yandexcloud_instance_platform_id": "s2.micro",
|
||||||
|
"__meta_yandexcloud_instance_resources_cores": "2",
|
||||||
|
"__meta_yandexcloud_instance_resources_core_fraction": "20",
|
||||||
|
"__meta_yandexcloud_instance_resources_memory": "4",
|
||||||
|
"__meta_yandexcloud_folder_id": "test",
|
||||||
|
"__meta_yandexcloud_instance_private_ip_0": "192.168.1.1",
|
||||||
|
"__meta_yandexcloud_instance_public_ip_0": "1.1.1.1",
|
||||||
|
"__meta_yandexcloud_instance_private_dns_0": "server-1.example.local",
|
||||||
|
"__meta_yandexcloud_instance_public_dns_0": "server-1.example.com",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
f(instances, labelssExpected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,77 +19,66 @@ func newTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*httpt
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewClientFromConfig(t *testing.T) {
|
func TestNewClientFromConfig(t *testing.T) {
|
||||||
allowed := true
|
f := func(h func(w http.ResponseWriter, r *http.Request), httpCfg *promauth.HTTPClientConfig, expectedMessage string) {
|
||||||
notAllowed := false
|
t.Helper()
|
||||||
newClientValidConfig := []struct {
|
|
||||||
httpCfg promauth.HTTPClientConfig
|
|
||||||
handler func(w http.ResponseWriter, r *http.Request)
|
|
||||||
expectedMessage string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
httpCfg: promauth.HTTPClientConfig{
|
|
||||||
FollowRedirects: &allowed,
|
|
||||||
},
|
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
switch r.URL.Path {
|
|
||||||
case "/redirected":
|
|
||||||
fmt.Fprint(w, "I'm here to serve you!!!")
|
|
||||||
default:
|
|
||||||
w.Header().Set("Location", "/redirected")
|
|
||||||
w.WriteHeader(http.StatusFound)
|
|
||||||
fmt.Fprint(w, "It should follow the redirect.")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expectedMessage: "I'm here to serve you!!!",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
httpCfg: promauth.HTTPClientConfig{
|
|
||||||
FollowRedirects: ¬Allowed,
|
|
||||||
},
|
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
switch r.URL.Path {
|
|
||||||
case "/redirected":
|
|
||||||
fmt.Fprint(w, "The redirection was followed.")
|
|
||||||
default:
|
|
||||||
w.Header().Set("Location", "/redirected")
|
|
||||||
w.WriteHeader(http.StatusFound)
|
|
||||||
fmt.Fprint(w, "I'm before redirect")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expectedMessage: "I'm before redirect",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, validConfig := range newClientValidConfig {
|
s, err := newTestServer(h)
|
||||||
testServer, err := newTestServer(validConfig.handler)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatalf("cannot create test server: %s", err)
|
||||||
}
|
}
|
||||||
defer testServer.Close()
|
defer s.Close()
|
||||||
|
|
||||||
client, err := NewClient("http://0.0.0.0:1234", nil, &proxy.URL{}, nil, &validConfig.httpCfg)
|
client, err := NewClient("http://0.0.0.0:1234", nil, &proxy.URL{}, nil, httpCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Can't create a client from this config: %+v", validConfig.httpCfg)
|
t.Fatalf("can't create a client from this config: %+v", httpCfg)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := client.client.client.Get(testServer.URL)
|
response, err := client.client.client.Get(s.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Can't connect to the test server using this config: %+v: %v", validConfig.httpCfg, err)
|
t.Fatalf("can't connect to the test server using this config: %+v: %v", httpCfg, err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message, err := io.ReadAll(response.Body)
|
message, err := io.ReadAll(response.Body)
|
||||||
response.Body.Close()
|
response.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Can't read the server response body using this config: %+v", validConfig.httpCfg)
|
t.Fatalf("Can't read the server response body using this config: %+v", httpCfg)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trimMessage := strings.TrimSpace(string(message))
|
trimMessage := strings.TrimSpace(string(message))
|
||||||
if validConfig.expectedMessage != trimMessage {
|
if expectedMessage != trimMessage {
|
||||||
t.Errorf("The expected message (%s) differs from the obtained message (%s) using this config: %+v",
|
t.Fatalf("The expected message (%s) differs from the obtained message (%s) using this config: %+v", expectedMessage, trimMessage, httpCfg)
|
||||||
validConfig.expectedMessage, trimMessage, validConfig.httpCfg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verify enabled redirects
|
||||||
|
allowed := true
|
||||||
|
handlerRedirect := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case "/redirected":
|
||||||
|
fmt.Fprint(w, "I'm here to serve you!!!")
|
||||||
|
default:
|
||||||
|
w.Header().Set("Location", "/redirected")
|
||||||
|
w.WriteHeader(http.StatusFound)
|
||||||
|
fmt.Fprint(w, "It should follow the redirect.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(handlerRedirect, &promauth.HTTPClientConfig{
|
||||||
|
FollowRedirects: &allowed,
|
||||||
|
}, "I'm here to serve you!!!")
|
||||||
|
|
||||||
|
// Verify disabled redirects
|
||||||
|
notAllowed := false
|
||||||
|
handlerNoRedirect := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case "/redirected":
|
||||||
|
fmt.Fprint(w, "The redirection was followed.")
|
||||||
|
default:
|
||||||
|
w.Header().Set("Location", "/redirected")
|
||||||
|
w.WriteHeader(http.StatusFound)
|
||||||
|
fmt.Fprint(w, "I'm before redirect")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(handlerNoRedirect, &promauth.HTTPClientConfig{
|
||||||
|
FollowRedirects: ¬Allowed,
|
||||||
|
}, "I'm before redirect")
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/graphite"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/graphite"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_streamContext_Read(t *testing.T) {
|
func TestStreamContextRead(t *testing.T) {
|
||||||
f := func(s string, rowsExpected *graphite.Rows) {
|
f := func(s string, rowsExpected *graphite.Rows) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
ctx := getStreamContext(strings.NewReader(s))
|
ctx := getStreamContext(strings.NewReader(s))
|
||||||
|
|
|
@ -4,53 +4,45 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Validate(t *testing.T) {
|
func TestValidate_Failure(t *testing.T) {
|
||||||
tests := []struct {
|
f := func(snapshotName string) {
|
||||||
name string
|
t.Helper()
|
||||||
snapshotName string
|
|
||||||
want bool
|
err := Validate(snapshotName)
|
||||||
}{
|
if err == nil {
|
||||||
{
|
t.Fatalf("expecting non-nil error")
|
||||||
name: "empty snapshot name",
|
}
|
||||||
snapshotName: "",
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "short snapshot name",
|
|
||||||
snapshotName: "",
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "short first part of the snapshot name",
|
|
||||||
snapshotName: "2022050312163-16EB56ADB4110CF2",
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "short second part of the snapshot name",
|
|
||||||
snapshotName: "20220503121638-16EB56ADB4110CF",
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "correct snapshot name",
|
|
||||||
snapshotName: "20220503121638-16EB56ADB4110CF2",
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid time part snapshot name",
|
|
||||||
snapshotName: "00000000000000-16EB56ADB4110CF2",
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not enough parts of the snapshot name",
|
|
||||||
snapshotName: "2022050312163816EB56ADB4110CF2",
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if err := Validate(tt.snapshotName); (err == nil) != tt.want {
|
|
||||||
t.Errorf("checkSnapshotName() = %v, want %v", err, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// empty snapshot name
|
||||||
|
f("")
|
||||||
|
|
||||||
|
// short snapshot name
|
||||||
|
f("foo")
|
||||||
|
|
||||||
|
// short first part of the snapshot name
|
||||||
|
f("2022050312163-16EB56ADB4110CF2")
|
||||||
|
|
||||||
|
// invalid time part snapshot name
|
||||||
|
f("00000000000000-16EB56ADB4110CF2")
|
||||||
|
|
||||||
|
// not enough parts of the snapshot name
|
||||||
|
f("2022050312163816EB56ADB4110CF2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidate_Success(t *testing.T) {
|
||||||
|
f := func(snapshotName string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
err := Validate(snapshotName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("checkSnapshotName() error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// short second part of the snapshot name - this is OK
|
||||||
|
f("20220503121638-16EB56ADB4110CF")
|
||||||
|
|
||||||
|
//correct snapshot name
|
||||||
|
f("20220503121638-16EB56ADB4110CF2")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue