mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-04-20 16:09:25 +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
33bd5ccbab
commit
9edeecabc8
35 changed files with 1795 additions and 2272 deletions
lib
httpserver
httputils
logstorage
promscrape
discovery
digitalocean
docker
dockerswarm
eureka
http
kubernetes
kuma
nomad
openstack
yandexcloud
discoveryutils
protoparser/graphite/stream
snapshot/snapshotutil
|
@ -135,9 +135,13 @@ func TestAuthKeyMetrics(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHandlerWrapper(t *testing.T) {
|
||||
*headerHSTS = "foo"
|
||||
*headerFrameOptions = "bar"
|
||||
*headerCSP = "baz"
|
||||
const hstsHeader = "foo"
|
||||
const frameOptionsHeader = "bar"
|
||||
const cspHeader = "baz"
|
||||
|
||||
*headerHSTS = hstsHeader
|
||||
*headerFrameOptions = frameOptionsHeader
|
||||
*headerCSP = cspHeader
|
||||
defer func() {
|
||||
*headerHSTS = ""
|
||||
*headerFrameOptions = ""
|
||||
|
@ -152,13 +156,14 @@ func TestHandlerWrapper(t *testing.T) {
|
|||
return true
|
||||
})
|
||||
|
||||
if w.Header().Get("Strict-Transport-Security") != "foo" {
|
||||
t.Errorf("HSTS header not set")
|
||||
h := w.Header()
|
||||
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" {
|
||||
t.Errorf("X-Frame-Options header not set")
|
||||
if got := h.Get("X-Frame-Options"); got != frameOptionsHeader {
|
||||
t.Fatalf("unexpected X-Frame-Options header; got %q; want %q", got, frameOptionsHeader)
|
||||
}
|
||||
if w.Header().Get("Content-Security-Policy") != "baz" {
|
||||
t.Errorf("CSP header not set")
|
||||
if got := h.Get("Content-Security-Policy"); got != cspHeader {
|
||||
t.Fatalf("unexpected CSP header; got %q; want %q", got, cspHeader)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,28 +9,27 @@ func TestTLSConfig(t *testing.T) {
|
|||
insecureSkipVerify = true
|
||||
tlsCfg, err := TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %s", err)
|
||||
t.Fatalf("unexpected error %s", err)
|
||||
}
|
||||
if tlsCfg == nil {
|
||||
t.Errorf("expected tlsConfig to be set, got nil")
|
||||
return
|
||||
t.Fatalf("expected tlsConfig to be set, got nil")
|
||||
}
|
||||
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 {
|
||||
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"
|
||||
_, err = TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||
if err == nil {
|
||||
t.Errorf("expected keypair error, got nil")
|
||||
t.Fatalf("expected keypair error, got nil")
|
||||
}
|
||||
certFile = ""
|
||||
CAFile = "/path/to/nonexisting/cert/file"
|
||||
_, err = TLSConfig(certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||
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"
|
||||
_, err := Transport(URL, certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %s", err)
|
||||
t.Fatalf("unexpected error %s", err)
|
||||
}
|
||||
URL = "https://victoriametrics.com"
|
||||
tr, err := Transport(URL, certFile, keyFile, CAFile, serverName, insecureSkipVerify)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %s", err)
|
||||
t.Fatalf("unexpected error %s", err)
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
return
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if got.String() != expected.String() {
|
||||
|
|
|
@ -5,20 +5,21 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func Test_parseAPIResponse(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *listDropletResponse
|
||||
wantErr bool
|
||||
}{
|
||||
func TestParseAPIResponse(t *testing.T) {
|
||||
f := func(data string, responseExpected *listDropletResponse) {
|
||||
t.Helper()
|
||||
|
||||
{
|
||||
name: "simple parse",
|
||||
args: args{data: []byte(`{
|
||||
response, err := parseAPIResponse([]byte(data))
|
||||
if err != nil {
|
||||
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": [
|
||||
{
|
||||
"id": 3164444,
|
||||
|
@ -88,88 +89,70 @@ func Test_parseAPIResponse(t *testing.T) {
|
|||
"next": "https://api.digitalocean.com/v2/droplets?page=2&per_page=1"
|
||||
}
|
||||
}
|
||||
}`)},
|
||||
want: &listDropletResponse{
|
||||
Droplets: []droplet{
|
||||
{
|
||||
Image: struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
}(struct {
|
||||
Name string
|
||||
Slug string
|
||||
}{Name: "14.04 x64", Slug: "ubuntu-16-04-x64"}),
|
||||
Region: struct {
|
||||
Slug string `json:"slug"`
|
||||
}(struct{ Slug string }{Slug: "nyc3"}),
|
||||
Networks: networks{
|
||||
V6: []network{
|
||||
{
|
||||
IPAddress: "2604:A880:0800:0010:0000:0000:02DD:4001",
|
||||
Type: "public",
|
||||
},
|
||||
},
|
||||
V4: []network{
|
||||
{
|
||||
IPAddress: "104.236.32.182",
|
||||
Type: "public",
|
||||
},
|
||||
},
|
||||
}`
|
||||
|
||||
responseExpected := &listDropletResponse{
|
||||
Droplets: []droplet{
|
||||
{
|
||||
Image: dropletImage{
|
||||
Name: "14.04 x64",
|
||||
Slug: "ubuntu-16-04-x64",
|
||||
},
|
||||
Region: dropletRegion{
|
||||
Slug: "nyc3",
|
||||
},
|
||||
Networks: networks{
|
||||
V6: []network{
|
||||
{
|
||||
IPAddress: "2604:A880:0800:0010:0000:0000:02DD:4001",
|
||||
Type: "public",
|
||||
},
|
||||
},
|
||||
V4: []network{
|
||||
{
|
||||
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{
|
||||
Pages: struct {
|
||||
Last string `json:"last,omitempty"`
|
||||
Next string `json:"next,omitempty"`
|
||||
}(struct {
|
||||
Last string
|
||||
Next string
|
||||
}{Last: "https://api.digitalocean.com/v2/droplets?page=3&per_page=1", Next: "https://api.digitalocean.com/v2/droplets?page=2&per_page=1"}),
|
||||
},
|
||||
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{
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, responseExpected)
|
||||
}
|
||||
|
||||
func Test_getDroplets(t *testing.T) {
|
||||
type args struct {
|
||||
getAPIResponse func(string) ([]byte, error)
|
||||
func TestGetDroplets(t *testing.T) {
|
||||
f := func(getAPIResponse func(string) ([]byte, error), expectedDropletCount int) {
|
||||
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
|
||||
args args
|
||||
wantDropletCount int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "get 4 droples",
|
||||
args: args{
|
||||
func(s string) ([]byte, error) {
|
||||
var resp []byte
|
||||
switch s {
|
||||
case dropletsAPIPath:
|
||||
// return next
|
||||
resp = []byte(`{ "droplets": [
|
||||
|
||||
getAPIResponse := func(s string) ([]byte, error) {
|
||||
var resp []byte
|
||||
switch s {
|
||||
case dropletsAPIPath:
|
||||
// return next
|
||||
resp = []byte(`{ "droplets": [
|
||||
{
|
||||
"id": 3164444,
|
||||
"name": "example.com",
|
||||
|
@ -267,9 +250,9 @@ func Test_getDroplets(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}`)
|
||||
default:
|
||||
// return with empty next
|
||||
resp = []byte(`{ "droplets": [
|
||||
default:
|
||||
// return with empty next
|
||||
resp = []byte(`{ "droplets": [
|
||||
{
|
||||
"id": 3164444,
|
||||
"name": "example.com",
|
||||
|
@ -326,24 +309,8 @@ func Test_getDroplets(t *testing.T) {
|
|||
}
|
||||
]
|
||||
}`)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
f(getAPIResponse, 5)
|
||||
}
|
||||
|
|
|
@ -49,18 +49,22 @@ type droplet struct {
|
|||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
|
||||
Features []string `json:"features"`
|
||||
Image struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
} `json:"image"`
|
||||
SizeSlug string `json:"size_slug"`
|
||||
Networks networks `json:"networks"`
|
||||
Region struct {
|
||||
Slug string `json:"slug"`
|
||||
} `json:"region"`
|
||||
Tags []string `json:"tags"`
|
||||
VpcUUID string `json:"vpc_uuid"`
|
||||
Features []string `json:"features"`
|
||||
Image dropletImage `json:"image"`
|
||||
SizeSlug string `json:"size_slug"`
|
||||
Networks networks `json:"networks"`
|
||||
Region dropletRegion `json:"region"`
|
||||
Tags []string `json:"tags"`
|
||||
VpcUUID string `json:"vpc_uuid"`
|
||||
}
|
||||
|
||||
type dropletImage struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
}
|
||||
|
||||
type dropletRegion struct {
|
||||
Slug string `json:"slug"`
|
||||
}
|
||||
|
||||
func (d *droplet) getIPByNet(netVersion, netType string) string {
|
||||
|
@ -98,10 +102,12 @@ type listDropletResponse struct {
|
|||
}
|
||||
|
||||
type links struct {
|
||||
Pages struct {
|
||||
Last string `json:"last,omitempty"`
|
||||
Next string `json:"next,omitempty"`
|
||||
} `json:"pages,omitempty"`
|
||||
Pages linksPages `json:"pages,omitempty"`
|
||||
}
|
||||
|
||||
type linksPages struct {
|
||||
Last string `json:"last,omitempty"`
|
||||
Next string `json:"next,omitempty"`
|
||||
}
|
||||
|
||||
func (r *listDropletResponse) nextURLPath() (string, error) {
|
||||
|
|
|
@ -7,84 +7,68 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_addDropletLabels(t *testing.T) {
|
||||
type args struct {
|
||||
droplets []droplet
|
||||
defaultPort int
|
||||
func TestAddDropletLabels(t *testing.T) {
|
||||
f := func(droplets []droplet, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addDropletLabels(droplets, 9100)
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// base labels add test
|
||||
droplets := []droplet{
|
||||
{
|
||||
name: "base labels add test",
|
||||
args: args{
|
||||
droplets: []droplet{
|
||||
ID: 15,
|
||||
Tags: []string{"private", "test"},
|
||||
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,
|
||||
Tags: []string{"private", "test"},
|
||||
Status: "active",
|
||||
Name: "ubuntu-1",
|
||||
Region: struct {
|
||||
Slug string `json:"slug"`
|
||||
}(struct{ Slug string }{Slug: "do"}),
|
||||
Features: []string{"feature-1", "feature-2"},
|
||||
SizeSlug: "base-1",
|
||||
VpcUUID: "vpc-1",
|
||||
Image: struct {
|
||||
Name string `json:"name"`
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addDropletLabels(tt.args.droplets, tt.args.defaultPort)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
labelssExpected := []*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",
|
||||
}),
|
||||
}
|
||||
f(droplets, labelssExpected)
|
||||
}
|
||||
|
|
|
@ -11,24 +11,32 @@ import (
|
|||
|
||||
// See https://github.com/moby/moby/blob/314759dc2f4745925d8dec6d15acc7761c6e5c92/docs/api/v1.41.yaml#L4024
|
||||
type container struct {
|
||||
ID string
|
||||
Names []string
|
||||
Labels map[string]string
|
||||
Ports []struct {
|
||||
IP string
|
||||
PrivatePort int
|
||||
PublicPort int
|
||||
Type string
|
||||
}
|
||||
HostConfig struct {
|
||||
NetworkMode string
|
||||
}
|
||||
NetworkSettings struct {
|
||||
Networks map[string]struct {
|
||||
IPAddress string
|
||||
NetworkID string
|
||||
}
|
||||
}
|
||||
ID string
|
||||
Names []string
|
||||
Labels map[string]string
|
||||
Ports []containerPort
|
||||
HostConfig containerHostConfig
|
||||
NetworkSettings containerNetworkSettings
|
||||
}
|
||||
|
||||
type containerPort struct {
|
||||
IP string
|
||||
PrivatePort int
|
||||
PublicPort int
|
||||
Type 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) {
|
||||
|
|
|
@ -8,20 +8,20 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_parseContainers(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TePParseContainers(t *testing.T) {
|
||||
f := func(data string, resultExpected []container) {
|
||||
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
|
||||
args args
|
||||
want []container
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse two containers",
|
||||
args: args{
|
||||
data: []byte(`[
|
||||
|
||||
data := `[
|
||||
{
|
||||
"Id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700",
|
||||
"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",
|
||||
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: []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",
|
||||
},
|
||||
},
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
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",
|
||||
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: []struct {
|
||||
IP string
|
||||
PrivatePort int
|
||||
PublicPort int
|
||||
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",
|
||||
},
|
||||
},
|
||||
IP: "0.0.0.0",
|
||||
PrivatePort: 8080,
|
||||
PublicPort: 18082,
|
||||
Type: "tcp",
|
||||
},
|
||||
},
|
||||
HostConfig: containerHostConfig{
|
||||
NetworkMode: "bridge",
|
||||
},
|
||||
NetworkSettings: containerNetworkSettings{
|
||||
Networks: map[string]containerNetwork{
|
||||
"bridge": {
|
||||
IPAddress: "172.17.0.3",
|
||||
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
f(data, resultExpected)
|
||||
}
|
||||
|
||||
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(`[
|
||||
{
|
||||
"Name": "host",
|
||||
|
@ -314,204 +282,152 @@ func Test_addContainerLabels(t *testing.T) {
|
|||
}
|
||||
networkLabels := getNetworkLabelsByNetworkID(networks)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
c container
|
||||
want []*promutils.Labels
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "NetworkMode!=host",
|
||||
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: "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",
|
||||
}),
|
||||
},
|
||||
// NetworkMode != host
|
||||
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",
|
||||
},
|
||||
{
|
||||
name: "NetworkMode=host",
|
||||
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",
|
||||
}),
|
||||
},
|
||||
HostConfig: containerHostConfig{
|
||||
NetworkMode: "bridge",
|
||||
},
|
||||
{
|
||||
name: "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",
|
||||
NetworkSettings: containerNetworkSettings{
|
||||
Networks: map[string]containerNetwork{
|
||||
"host": {
|
||||
IPAddress: "172.17.0.2",
|
||||
NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634",
|
||||
},
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
labelss := addContainersLabels([]container{tt.c}, networkLabels, 8012, "foobar")
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("addContainersLabels() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
discoveryutils.TestEqualLabelss(t, labelss, tt.want)
|
||||
})
|
||||
// NetworkMode=host
|
||||
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: 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"
|
||||
)
|
||||
|
||||
func Test_addNetworkLabels(t *testing.T) {
|
||||
type args struct {
|
||||
networks []network
|
||||
func TestAddNetworkLabels(t *testing.T) {
|
||||
f := func(networks []network, labelssExpected []*promutils.Labels) {
|
||||
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
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// ingress network
|
||||
networks := []network{
|
||||
{
|
||||
name: "ingress network",
|
||||
args: args{
|
||||
networks: []network{
|
||||
{
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
Scope: "swarm",
|
||||
Name: "ingress",
|
||||
Labels: map[string]string{
|
||||
"key1": "value1",
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := getNetworkLabelsByNetworkID(tt.args.networks)
|
||||
var networkIDs []string
|
||||
for networkID := range got {
|
||||
networkIDs = append(networkIDs, networkID)
|
||||
}
|
||||
sort.Strings(networkIDs)
|
||||
var labelss []*promutils.Labels
|
||||
for _, networkID := range networkIDs {
|
||||
labelss = append(labelss, got[networkID])
|
||||
}
|
||||
discoveryutils.TestEqualLabelss(t, labelss, tt.want)
|
||||
})
|
||||
labelssExpected := []*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",
|
||||
}),
|
||||
}
|
||||
f(networks, labelssExpected)
|
||||
}
|
||||
|
||||
func Test_parseNetworks(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseNetworks(t *testing.T) {
|
||||
f := func(data string, resultExpected []network) {
|
||||
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
|
||||
args args
|
||||
want []network
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse two networks",
|
||||
args: args{
|
||||
data: []byte(`[
|
||||
|
||||
// parse two networks
|
||||
data := `[
|
||||
{
|
||||
"Name": "ingress",
|
||||
"Id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||
|
@ -132,39 +124,25 @@ func Test_parseNetworks(t *testing.T) {
|
|||
"key": "value"
|
||||
}
|
||||
}
|
||||
]`),
|
||||
]`
|
||||
resultExpected := []network{
|
||||
{
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
Scope: "swarm",
|
||||
Name: "ingress",
|
||||
Labels: map[string]string{
|
||||
"key1": "value1",
|
||||
},
|
||||
want: []network{
|
||||
{
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
Scope: "swarm",
|
||||
Name: "ingress",
|
||||
Labels: map[string]string{
|
||||
"key1": "value1",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
||||
Scope: "local",
|
||||
Name: "host",
|
||||
Labels: map[string]string{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
||||
Scope: "local",
|
||||
Name: "host",
|
||||
Labels: map[string]string{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, resultExpected)
|
||||
}
|
||||
|
|
|
@ -9,72 +9,64 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_addNetworkLabels(t *testing.T) {
|
||||
type args struct {
|
||||
networks []network
|
||||
func TestAddNetworkLabels(t *testing.T) {
|
||||
f := func(networks []network, labelssExpected []*promutils.Labels) {
|
||||
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
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// ingress network
|
||||
networks := []network{
|
||||
{
|
||||
name: "ingress network",
|
||||
args: args{
|
||||
networks: []network{
|
||||
{
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
Scope: "swarm",
|
||||
Name: "ingress",
|
||||
Labels: map[string]string{
|
||||
"key1": "value1",
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := getNetworkLabelsByNetworkID(tt.args.networks)
|
||||
var networkIDs []string
|
||||
for networkID := range got {
|
||||
networkIDs = append(networkIDs, networkID)
|
||||
}
|
||||
sort.Strings(networkIDs)
|
||||
var labelss []*promutils.Labels
|
||||
for _, networkID := range networkIDs {
|
||||
labelss = append(labelss, got[networkID])
|
||||
}
|
||||
discoveryutils.TestEqualLabelss(t, labelss, tt.want)
|
||||
})
|
||||
labelssExpected := []*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",
|
||||
}),
|
||||
}
|
||||
f(networks, labelssExpected)
|
||||
}
|
||||
|
||||
func Test_parseNetworks(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseNetworks(t *testing.T) {
|
||||
f := func(data string, resultExpected []network) {
|
||||
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
|
||||
args args
|
||||
want []network
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse two networks",
|
||||
args: args{
|
||||
data: []byte(`[
|
||||
|
||||
// parse two networks
|
||||
data := `[
|
||||
{
|
||||
"Name": "ingress",
|
||||
"Id": "qs0hog6ldlei9ct11pr3c77v1",
|
||||
|
@ -132,39 +124,25 @@ func Test_parseNetworks(t *testing.T) {
|
|||
"key": "value"
|
||||
}
|
||||
}
|
||||
]`),
|
||||
]`
|
||||
resultExpected := []network{
|
||||
{
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
Scope: "swarm",
|
||||
Name: "ingress",
|
||||
Labels: map[string]string{
|
||||
"key1": "value1",
|
||||
},
|
||||
want: []network{
|
||||
{
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Ingress: true,
|
||||
Scope: "swarm",
|
||||
Name: "ingress",
|
||||
Labels: map[string]string{
|
||||
"key1": "value1",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
||||
Scope: "local",
|
||||
Name: "host",
|
||||
Labels: map[string]string{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "317f0384d7e5f5c26304a0b04599f9f54bc08def4d0535059ece89955e9c4b7b",
|
||||
Scope: "local",
|
||||
Name: "host",
|
||||
Labels: map[string]string{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, resultExpected)
|
||||
}
|
||||
|
|
|
@ -10,32 +10,44 @@ import (
|
|||
|
||||
// See https://docs.docker.com/engine/api/v1.40/#tag/Node
|
||||
type node struct {
|
||||
ID string
|
||||
Spec struct {
|
||||
Labels map[string]string
|
||||
Role string
|
||||
Availability string
|
||||
}
|
||||
Description struct {
|
||||
Hostname string
|
||||
Platform struct {
|
||||
Architecture string
|
||||
OS string
|
||||
}
|
||||
Engine struct {
|
||||
EngineVersion string
|
||||
}
|
||||
}
|
||||
Status struct {
|
||||
State string
|
||||
Message string
|
||||
Addr string
|
||||
}
|
||||
ManagerStatus struct {
|
||||
Leader bool
|
||||
Reachability string
|
||||
Addr string
|
||||
}
|
||||
ID string
|
||||
Spec nodeSpec
|
||||
Description nodeDescription
|
||||
Status nodeStatus
|
||||
ManagerStatus nodeManagerStatus
|
||||
}
|
||||
|
||||
type nodeSpec struct {
|
||||
Labels map[string]string
|
||||
Role string
|
||||
Availability string
|
||||
}
|
||||
|
||||
type nodeDescription struct {
|
||||
Hostname string
|
||||
Platform nodePlatform
|
||||
Engine nodeEngine
|
||||
}
|
||||
|
||||
type nodePlatform struct {
|
||||
Architecture string
|
||||
OS 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) {
|
||||
|
|
|
@ -8,20 +8,21 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_parseNodes(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseNodes(t *testing.T) {
|
||||
f := func(data string, resultExpected []node) {
|
||||
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
|
||||
args args
|
||||
want []node
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse ok",
|
||||
args: args{
|
||||
data: []byte(`[
|
||||
|
||||
// parse ok
|
||||
data := `[
|
||||
{
|
||||
"ID": "qauwmifceyvqs0sipvzu8oslu",
|
||||
"Version": {
|
||||
|
@ -51,131 +52,81 @@ func Test_parseNodes(t *testing.T) {
|
|||
}
|
||||
}
|
||||
]
|
||||
`),
|
||||
`
|
||||
resultExpected := []node{
|
||||
{
|
||||
ID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
Spec: nodeSpec{
|
||||
Role: "manager",
|
||||
Availability: "active",
|
||||
},
|
||||
want: []node{
|
||||
{
|
||||
ID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
Spec: struct {
|
||||
Labels map[string]string
|
||||
Role string
|
||||
Availability string
|
||||
}{Role: "manager", Availability: "active"},
|
||||
Status: struct {
|
||||
State string
|
||||
Message string
|
||||
Addr string
|
||||
}{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",
|
||||
},
|
||||
},
|
||||
Status: nodeStatus{
|
||||
State: "ready",
|
||||
Addr: "172.31.40.97",
|
||||
},
|
||||
Description: nodeDescription{
|
||||
Hostname: "ip-172-31-40-97",
|
||||
Platform: nodePlatform{
|
||||
Architecture: "x86_64",
|
||||
OS: "linux",
|
||||
},
|
||||
Engine: nodeEngine{
|
||||
EngineVersion: "19.03.11",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, resultExpected)
|
||||
}
|
||||
|
||||
func Test_addNodeLabels(t *testing.T) {
|
||||
type args struct {
|
||||
nodes []node
|
||||
port int
|
||||
func TestAddNodeLabels(t *testing.T) {
|
||||
f := func(nodes []node, port int, resultExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
result := addNodeLabels(nodes, port)
|
||||
discoveryutils.TestEqualLabelss(t, result, resultExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// add labels to one node
|
||||
nodes := []node{
|
||||
{
|
||||
name: "add labels to one node",
|
||||
args: args{
|
||||
nodes: []node{
|
||||
{
|
||||
ID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
Spec: struct {
|
||||
Labels map[string]string
|
||||
Role string
|
||||
Availability string
|
||||
}{Role: "manager", Availability: "active"},
|
||||
Status: struct {
|
||||
State string
|
||||
Message string
|
||||
Addr string
|
||||
}{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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
port: 9100,
|
||||
ID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
Spec: nodeSpec{
|
||||
Role: "manager",
|
||||
Availability: "active",
|
||||
},
|
||||
Status: nodeStatus{
|
||||
State: "ready",
|
||||
Addr: "172.31.40.97",
|
||||
},
|
||||
Description: nodeDescription{
|
||||
Hostname: "ip-172-31-40-97",
|
||||
Platform: nodePlatform{
|
||||
Architecture: "x86_64",
|
||||
OS: "linux",
|
||||
},
|
||||
Engine: nodeEngine{
|
||||
EngineVersion: "19.03.11",
|
||||
},
|
||||
},
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addNodeLabels(tt.args.nodes, tt.args.port)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
labelssExpected := []*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",
|
||||
}),
|
||||
}
|
||||
f(nodes, 9100, labelssExpected)
|
||||
}
|
||||
|
|
|
@ -12,31 +12,45 @@ import (
|
|||
|
||||
// https://docs.docker.com/engine/api/v1.40/#tag/Service
|
||||
type service struct {
|
||||
ID string
|
||||
Spec struct {
|
||||
Labels map[string]string
|
||||
Name string
|
||||
TaskTemplate struct {
|
||||
ContainerSpec struct {
|
||||
Hostname string
|
||||
Image string
|
||||
}
|
||||
}
|
||||
Mode struct {
|
||||
Global interface{}
|
||||
Replicated interface{}
|
||||
}
|
||||
}
|
||||
UpdateStatus struct {
|
||||
State string
|
||||
}
|
||||
Endpoint struct {
|
||||
Ports []portConfig
|
||||
VirtualIPs []struct {
|
||||
NetworkID string
|
||||
Addr string
|
||||
}
|
||||
}
|
||||
ID string
|
||||
Spec serviceSpec
|
||||
UpdateStatus serviceUpdateStatus
|
||||
Endpoint serviceEndpoint
|
||||
}
|
||||
|
||||
type serviceSpec struct {
|
||||
Labels map[string]string
|
||||
Name string
|
||||
TaskTemplate taskTemplate
|
||||
Mode serviceSpecMode
|
||||
}
|
||||
|
||||
type taskTemplate struct {
|
||||
ContainerSpec containerSpec
|
||||
}
|
||||
|
||||
type containerSpec struct {
|
||||
Hostname string
|
||||
Image 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 {
|
||||
|
|
|
@ -8,20 +8,21 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_parseServicesResponse(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseServicesResponse(t *testing.T) {
|
||||
f := func(data string, servicesExpected []service) {
|
||||
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
|
||||
args args
|
||||
want []service
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse ok",
|
||||
args: args{
|
||||
data: []byte(`[
|
||||
|
||||
// parse ok
|
||||
data := `[
|
||||
{
|
||||
"ID": "tgsci5gd31aai3jyudv98pqxf",
|
||||
"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{
|
||||
{
|
||||
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: "",
|
||||
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",
|
||||
},
|
||||
Endpoint: serviceEndpoint{
|
||||
Ports: []portConfig{
|
||||
{
|
||||
Protocol: "tcp",
|
||||
PublishMode: "ingress",
|
||||
PublishedPort: 8081,
|
||||
},
|
||||
},
|
||||
VirtualIPs: []virtualIP{
|
||||
{
|
||||
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Addr: "10.0.0.3/24",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, servicesExpected)
|
||||
}
|
||||
|
||||
func Test_addServicesLabels(t *testing.T) {
|
||||
type args struct {
|
||||
services []service
|
||||
networksLabels map[string]*promutils.Labels
|
||||
port int
|
||||
func TestAddServicesLabels(t *testing.T) {
|
||||
f := func(services []service, networksLabels map[string]*promutils.Labels, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addServicesLabels(services, networksLabels, 9100)
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// add 2 services with network labels join
|
||||
services := []service{
|
||||
{
|
||||
name: "add 2 services with network labels join",
|
||||
args: args{
|
||||
port: 9100,
|
||||
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",
|
||||
}),
|
||||
ID: "tgsci5gd31aai3jyudv98pqxf",
|
||||
Spec: serviceSpec{
|
||||
Labels: map[string]string{},
|
||||
Name: "redis2",
|
||||
TaskTemplate: taskTemplate{
|
||||
ContainerSpec: containerSpec{
|
||||
Hostname: "node1",
|
||||
Image: "redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842",
|
||||
},
|
||||
},
|
||||
services: []service{
|
||||
Mode: serviceSpecMode{
|
||||
Replicated: map[string]interface{}{},
|
||||
},
|
||||
},
|
||||
Endpoint: serviceEndpoint{
|
||||
Ports: []portConfig{
|
||||
{
|
||||
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",
|
||||
},
|
||||
}, VirtualIPs: []struct {
|
||||
NetworkID string
|
||||
Addr string
|
||||
}{
|
||||
{
|
||||
NetworkID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
Addr: "10.0.0.3/24",
|
||||
},
|
||||
},
|
||||
},
|
||||
Protocol: "tcp",
|
||||
Name: "redis",
|
||||
PublishMode: "ingress",
|
||||
},
|
||||
},
|
||||
VirtualIPs: []virtualIP{
|
||||
{
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addServicesLabels(tt.args.services, tt.args.networksLabels, tt.args.port)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
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",
|
||||
}),
|
||||
}
|
||||
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
|
||||
NodeID string
|
||||
DesiredState string
|
||||
NetworksAttachments []struct {
|
||||
Addresses []string
|
||||
Network struct {
|
||||
ID string
|
||||
}
|
||||
}
|
||||
Status struct {
|
||||
State string
|
||||
ContainerStatus struct {
|
||||
ContainerID string
|
||||
}
|
||||
PortStatus struct {
|
||||
Ports []portConfig
|
||||
}
|
||||
}
|
||||
Spec struct {
|
||||
ContainerSpec struct {
|
||||
Labels map[string]string
|
||||
}
|
||||
}
|
||||
Slot int
|
||||
NetworksAttachments []networkAttachment
|
||||
Status taskStatus
|
||||
Spec taskSpec
|
||||
Slot int
|
||||
}
|
||||
|
||||
type networkAttachment struct {
|
||||
Addresses []string
|
||||
Network network
|
||||
}
|
||||
|
||||
type taskStatus struct {
|
||||
State string
|
||||
ContainerStatus containerStatus
|
||||
PortStatus portStatus
|
||||
}
|
||||
|
||||
type containerStatus struct {
|
||||
ContainerID string
|
||||
}
|
||||
|
||||
type portStatus struct {
|
||||
Ports []portConfig
|
||||
}
|
||||
|
||||
type taskSpec struct {
|
||||
ContainerSpec taskContainerSpec
|
||||
}
|
||||
|
||||
type taskContainerSpec struct {
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
func getTasksLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
||||
|
|
|
@ -8,20 +8,21 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_parseTasks(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseTasks(t *testing.T) {
|
||||
f := func(data string, tasksExpected []task) {
|
||||
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
|
||||
args args
|
||||
want []task
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse ok",
|
||||
args: args{
|
||||
data: []byte(`[
|
||||
|
||||
// parse ok
|
||||
data := `[
|
||||
{
|
||||
"ID": "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||
"Version": {
|
||||
|
@ -63,297 +64,217 @@ func Test_parseTasks(t *testing.T) {
|
|||
"DesiredState": "running"
|
||||
}
|
||||
]
|
||||
`),
|
||||
},
|
||||
want: []task{
|
||||
{
|
||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
Spec: struct {
|
||||
ContainerSpec struct {
|
||||
Labels map[string]string
|
||||
}
|
||||
}{
|
||||
ContainerSpec: struct {
|
||||
Labels map[string]string
|
||||
}{
|
||||
Labels: map[string]string{
|
||||
"label1": "value1",
|
||||
},
|
||||
},
|
||||
`
|
||||
|
||||
tasksExpected := []task{
|
||||
{
|
||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
Spec: taskSpec{
|
||||
ContainerSpec: taskContainerSpec{
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, tasksExpected)
|
||||
}
|
||||
|
||||
func Test_addTasksLabels(t *testing.T) {
|
||||
type args struct {
|
||||
tasks []task
|
||||
nodesLabels []*promutils.Labels
|
||||
servicesLabels []*promutils.Labels
|
||||
networksLabels map[string]*promutils.Labels
|
||||
services []service
|
||||
port int
|
||||
func TestAddTasksLabels(t *testing.T) {
|
||||
f := func(tasks []task, nodesLabels []*promutils.Labels, networkLabels map[string]*promutils.Labels, services []service, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addTasksLabels(tasks, nodesLabels, nil, networkLabels, services, 9100)
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// adds 1 task with nodes labels
|
||||
tasks := []task{
|
||||
{
|
||||
name: "adds 1 task with nodes labels",
|
||||
args: args{
|
||||
port: 9100,
|
||||
tasks: []task{
|
||||
{
|
||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
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 }{
|
||||
Ports: []portConfig{
|
||||
{
|
||||
PublishMode: "ingress",
|
||||
Name: "redis",
|
||||
Protocol: "tcp",
|
||||
PublishedPort: 6379,
|
||||
},
|
||||
},
|
||||
}},
|
||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||
ServiceID: "t91nf284wzle1ya09lqvyjgnq",
|
||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
DesiredState: "running",
|
||||
Slot: 1,
|
||||
Status: taskStatus{
|
||||
State: "running",
|
||||
ContainerStatus: containerStatus{
|
||||
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
||||
},
|
||||
PortStatus: portStatus{
|
||||
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",
|
||||
args: args{
|
||||
port: 9100,
|
||||
tasks: []task{
|
||||
{
|
||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||
ServiceID: "tgsci5gd31aai3jyudv98pqxf",
|
||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
DesiredState: "running",
|
||||
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 }{}},
|
||||
ID: "t4rdm7j2y9yctbrksiwvsgpu5",
|
||||
ServiceID: "tgsci5gd31aai3jyudv98pqxf",
|
||||
NodeID: "qauwmifceyvqs0sipvzu8oslu",
|
||||
DesiredState: "running",
|
||||
Slot: 1,
|
||||
NetworksAttachments: []networkAttachment{
|
||||
{
|
||||
Network: network{
|
||||
ID: "qs0hog6ldlei9ct11pr3c77v1",
|
||||
},
|
||||
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{
|
||||
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",
|
||||
}),
|
||||
Status: taskStatus{
|
||||
State: "running",
|
||||
ContainerStatus: containerStatus{
|
||||
ContainerID: "33034b69f6fa5f808098208752fd1fe4e0e1ca86311988cea6a73b998cdc62e8",
|
||||
},
|
||||
PortStatus: portStatus{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addTasksLabels(tt.args.tasks, tt.args.nodesLabels, tt.args.servicesLabels, tt.args.networksLabels, tt.args.services, tt.args.port)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
|
||||
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: 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"
|
||||
)
|
||||
|
||||
func Test_parseAPIResponse(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseAPIResponse(t *testing.T) {
|
||||
f := func(data string, resultExpected *applications) {
|
||||
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
|
||||
args args
|
||||
want *applications
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse ok 1 app with instance",
|
||||
args: args{
|
||||
data: []byte(`<applications>
|
||||
|
||||
// parse ok 1 app with instance
|
||||
data := `<applications>
|
||||
<versions__delta>1</versions__delta>
|
||||
<apps__hashcode>UP_1_</apps__hashcode>
|
||||
<application>
|
||||
|
@ -55,53 +56,40 @@ func Test_parseAPIResponse(t *testing.T) {
|
|||
<actionType>ADDED</actionType>
|
||||
</instance>
|
||||
</application>
|
||||
</applications>`),
|
||||
},
|
||||
want: &applications{
|
||||
Applications: []Application{
|
||||
</applications>`
|
||||
|
||||
resultExpected := &applications{
|
||||
Applications: []Application{
|
||||
{
|
||||
Name: "HELLO-NETFLIX-OSS",
|
||||
Instances: []Instance{
|
||||
{
|
||||
Name: "HELLO-NETFLIX-OSS",
|
||||
Instances: []Instance{
|
||||
{
|
||||
HostName: "98de25ebef42",
|
||||
HomePageURL: "http://98de25ebef42:8080/",
|
||||
StatusPageURL: "http://98de25ebef42:8080/Status",
|
||||
HealthCheckURL: "http://98de25ebef42:8080/healthcheck",
|
||||
App: "HELLO-NETFLIX-OSS",
|
||||
IPAddr: "10.10.0.3",
|
||||
VipAddress: "HELLO-NETFLIX-OSS",
|
||||
SecureVipAddress: "",
|
||||
Status: "UP",
|
||||
Port: Port{
|
||||
Enabled: true,
|
||||
Port: 8080,
|
||||
},
|
||||
SecurePort: Port{
|
||||
Port: 443,
|
||||
},
|
||||
DataCenterInfo: DataCenterInfo{
|
||||
Name: "MyOwn",
|
||||
},
|
||||
Metadata: MetaData{},
|
||||
CountryID: 1,
|
||||
InstanceID: "",
|
||||
},
|
||||
HostName: "98de25ebef42",
|
||||
HomePageURL: "http://98de25ebef42:8080/",
|
||||
StatusPageURL: "http://98de25ebef42:8080/Status",
|
||||
HealthCheckURL: "http://98de25ebef42:8080/healthcheck",
|
||||
App: "HELLO-NETFLIX-OSS",
|
||||
IPAddr: "10.10.0.3",
|
||||
VipAddress: "HELLO-NETFLIX-OSS",
|
||||
SecureVipAddress: "",
|
||||
Status: "UP",
|
||||
Port: Port{
|
||||
Enabled: true,
|
||||
Port: 8080,
|
||||
},
|
||||
SecurePort: Port{
|
||||
Port: 443,
|
||||
},
|
||||
DataCenterInfo: DataCenterInfo{
|
||||
Name: "MyOwn",
|
||||
},
|
||||
Metadata: MetaData{},
|
||||
CountryID: 1,
|
||||
InstanceID: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, resultExpected)
|
||||
}
|
||||
|
|
|
@ -7,74 +7,65 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_addInstanceLabels(t *testing.T) {
|
||||
type args struct {
|
||||
applications *applications
|
||||
func TestAddInstanceLabels(t *testing.T) {
|
||||
f := func(applications *applications, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addInstanceLabels(applications)
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
{
|
||||
name: "1 application",
|
||||
args: args{
|
||||
applications: &applications{
|
||||
Applications: []Application{
|
||||
{
|
||||
Name: "test-app",
|
||||
Instances: []Instance{
|
||||
|
||||
// one application
|
||||
applications := &applications{
|
||||
Applications: []Application{
|
||||
{
|
||||
Name: "test-app",
|
||||
Instances: []Instance{
|
||||
{
|
||||
Status: "Ok",
|
||||
HealthCheckURL: "some-url",
|
||||
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{
|
||||
{
|
||||
Status: "Ok",
|
||||
HealthCheckURL: "some-url",
|
||||
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,
|
||||
},
|
||||
Content: "value-1",
|
||||
XMLName: struct{ Space, Local string }{Local: "key-1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addInstanceLabels(tt.args.applications)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
labelssExpected := []*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",
|
||||
}),
|
||||
}
|
||||
f(applications, labelssExpected)
|
||||
}
|
||||
|
|
|
@ -7,45 +7,30 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_parseAPIResponse(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
path string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []httpGroupTarget
|
||||
wantErr bool
|
||||
}{
|
||||
func TestParseAPIResponse(t *testing.T) {
|
||||
f := func(data, path string, resultExpected []httpGroupTarget) {
|
||||
t.Helper()
|
||||
|
||||
{
|
||||
name: "parse ok",
|
||||
args: args{
|
||||
path: "/ok",
|
||||
data: []byte(`[
|
||||
result, err := parseAPIResponse([]byte(data), path)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// parse ok
|
||||
data := `[
|
||||
{"targets": ["http://target-1:9100","http://target-2:9150"],
|
||||
"labels": {"label-1":"value-1"} }
|
||||
]`),
|
||||
},
|
||||
want: []httpGroupTarget{
|
||||
{
|
||||
Labels: promutils.NewLabelsFromMap(map[string]string{"label-1": "value-1"}),
|
||||
Targets: []string{"http://target-1:9100", "http://target-2:9150"},
|
||||
},
|
||||
},
|
||||
]`
|
||||
path := "/ok"
|
||||
resultExpected := []httpGroupTarget{
|
||||
{
|
||||
Labels: promutils.NewLabelsFromMap(map[string]string{"label-1": "value-1"}),
|
||||
Targets: []string{"http://target-1:9100", "http://target-2:9150"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, path, resultExpected)
|
||||
}
|
||||
|
|
|
@ -7,45 +7,34 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_addHTTPTargetLabels(t *testing.T) {
|
||||
type args struct {
|
||||
src []httpGroupTarget
|
||||
func TestAddHTTPTargetLabels(t *testing.T) {
|
||||
f := func(src []httpGroupTarget, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addHTTPTargetLabels(src, "http://foo.bar/baz?aaa=bb")
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// add ok
|
||||
src := []httpGroupTarget{
|
||||
{
|
||||
name: "add ok",
|
||||
args: args{
|
||||
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",
|
||||
}),
|
||||
},
|
||||
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"}),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addHTTPTargetLabels(tt.args.src, "http://foo.bar/baz?aaa=bb")
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
labelssExpected := []*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",
|
||||
}),
|
||||
}
|
||||
f(src, labelssExpected)
|
||||
}
|
||||
|
|
|
@ -936,9 +936,12 @@ func (uw *urlWatcher) maybeUpdateDependedScrapeWorksLocked() {
|
|||
// Bookmark is a bookmark message from Kubernetes Watch API.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#watch-bookmarks
|
||||
type Bookmark struct {
|
||||
Metadata struct {
|
||||
ResourceVersion string
|
||||
}
|
||||
Metadata BookmarkMetadata
|
||||
}
|
||||
|
||||
// BookmarkMetadata is metadata for Bookmark
|
||||
type BookmarkMetadata struct {
|
||||
ResourceVersion string
|
||||
}
|
||||
|
||||
func parseBookmark(data []byte) (*Bookmark, error) {
|
||||
|
|
|
@ -12,10 +12,10 @@ func TestParseEndpointSliceListFail(t *testing.T) {
|
|||
r := bytes.NewBufferString(data)
|
||||
objectsByKey, _, err := parseEndpointSliceList(r)
|
||||
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 {
|
||||
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)
|
||||
objectsByKey, meta, err := parseEndpointSliceList(r)
|
||||
if err != nil {
|
||||
t.Errorf("cannot parse data for EndpointSliceList: %v", err)
|
||||
return
|
||||
t.Fatalf("cannot parse data for EndpointSliceList: %v", err)
|
||||
}
|
||||
expectedResourceVersion := "1177"
|
||||
if meta.ResourceVersion != expectedResourceVersion {
|
||||
|
|
|
@ -20,21 +20,27 @@ type apiConfig struct {
|
|||
// Config represent configuration file for kubernetes API server connection
|
||||
// https://github.com/kubernetes/client-go/blob/master/tools/clientcmd/api/v1/types.go#L28
|
||||
type Config struct {
|
||||
Kind string `yaml:"kind,omitempty"`
|
||||
APIVersion string `yaml:"apiVersion,omitempty"`
|
||||
Clusters []struct {
|
||||
Name string `yaml:"name"`
|
||||
Cluster *Cluster `yaml:"cluster"`
|
||||
} `yaml:"clusters"`
|
||||
AuthInfos []struct {
|
||||
Name string `yaml:"name"`
|
||||
AuthInfo *AuthInfo `yaml:"user"`
|
||||
} `yaml:"users"`
|
||||
Contexts []struct {
|
||||
Name string `yaml:"name"`
|
||||
Context *Context `yaml:"context"`
|
||||
} `yaml:"contexts"`
|
||||
CurrentContext string `yaml:"current-context"`
|
||||
Kind string `yaml:"kind,omitempty"`
|
||||
APIVersion string `yaml:"apiVersion,omitempty"`
|
||||
Clusters []configCluster `yaml:"clusters"`
|
||||
AuthInfos []authInfo `yaml:"users"`
|
||||
Contexts []configContext `yaml:"contexts"`
|
||||
CurrentContext string `yaml:"current-context"`
|
||||
}
|
||||
|
||||
type configCluster struct {
|
||||
Name string `yaml:"name"`
|
||||
Cluster *Cluster `yaml:"cluster"`
|
||||
}
|
||||
|
||||
type authInfo struct {
|
||||
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
|
||||
|
|
|
@ -264,18 +264,22 @@ type discoveryRequestNode struct {
|
|||
// 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
|
||||
type discoveryResponse struct {
|
||||
VersionInfo string `json:"version_info"`
|
||||
Resources []struct {
|
||||
Mesh string `json:"mesh"`
|
||||
Service string `json:"service"`
|
||||
Targets []struct {
|
||||
Name string `json:"name"`
|
||||
Scheme string `json:"scheme"`
|
||||
Address string `json:"address"`
|
||||
MetricsPath string `json:"metrics_path"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
} `json:"targets"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
} `json:"resources"`
|
||||
Nonce string `json:"nonce"`
|
||||
VersionInfo string `json:"version_info"`
|
||||
Resources []resource `json:"resources"`
|
||||
Nonce string `json:"nonce"`
|
||||
}
|
||||
|
||||
type resource struct {
|
||||
Mesh string `json:"mesh"`
|
||||
Service string `json:"service"`
|
||||
Targets []target `json:"targets"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
}
|
||||
|
||||
type target struct {
|
||||
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.
|
||||
// See https://developer.hashicorp.com/nomad/api-docs/services#list-services
|
||||
type ServiceList struct {
|
||||
Namespace string `json:"Namespace"`
|
||||
Services []struct {
|
||||
ServiceName string `json:"ServiceName"`
|
||||
Tags []string `json:"Tags"`
|
||||
} `json:"Services"`
|
||||
Namespace string `json:"Namespace"`
|
||||
Services []service `json:"Services"`
|
||||
}
|
||||
|
||||
type service struct {
|
||||
ServiceName string `json:"ServiceName"`
|
||||
Tags []string `json:"Tags"`
|
||||
}
|
||||
|
||||
// Service is Nomad service.
|
||||
|
|
|
@ -14,10 +14,12 @@ import (
|
|||
//
|
||||
// See https://docs.openstack.org/api-ref/identity/v3/#authentication-and-token-management
|
||||
type authResponse struct {
|
||||
Token struct {
|
||||
ExpiresAt time.Time `json:"expires_at,omitempty"`
|
||||
Catalog []catalogItem `json:"catalog,omitempty"`
|
||||
}
|
||||
Token authToken
|
||||
}
|
||||
|
||||
type authToken struct {
|
||||
ExpiresAt time.Time `json:"expires_at,omitempty"`
|
||||
Catalog []catalogItem `json:"catalog,omitempty"`
|
||||
}
|
||||
|
||||
type catalogItem struct {
|
||||
|
|
|
@ -1,124 +1,104 @@
|
|||
package openstack
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
|
||||
)
|
||||
|
||||
func Test_buildAuthRequestBody1(t *testing.T) {
|
||||
type args struct {
|
||||
sdc *SDConfig
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
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)
|
||||
}
|
||||
})
|
||||
func TestBuildAuthRequestBody_Failure(t *testing.T) {
|
||||
f := func(sdc *SDConfig) {
|
||||
t.Helper()
|
||||
|
||||
_, err := buildAuthRequestBody(sdc)
|
||||
if err == nil {
|
||||
t.Fatalf("expecting non-nil error")
|
||||
}
|
||||
}
|
||||
|
||||
// empty config
|
||||
f(&SDConfig{})
|
||||
}
|
||||
|
||||
func Test_getComputeEndpointURL1(t *testing.T) {
|
||||
type args struct {
|
||||
catalog []catalogItem
|
||||
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
|
||||
}
|
||||
func TestBuildAuthRequestBody_Success(t *testing.T) {
|
||||
f := func(sdc *SDConfig, resultExpected string) {
|
||||
t.Helper()
|
||||
|
||||
if !tt.wantErr && !reflect.DeepEqual(got.String(), tt.want) {
|
||||
t.Errorf("getComputeEndpointURL() got = %v, want %v", got.String(), tt.want)
|
||||
}
|
||||
})
|
||||
result, err := buildAuthRequestBody(sdc)
|
||||
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
|
||||
type hypervisorDetail struct {
|
||||
Hypervisors []hypervisor `json:"hypervisors"`
|
||||
Links []struct {
|
||||
HREF string `json:"href"`
|
||||
Rel string `json:"rel,omitempty"`
|
||||
} `json:"hypervisors_links,omitempty"`
|
||||
Hypervisors []hypervisor `json:"hypervisors"`
|
||||
Links []hypervisorLink `json:"hypervisors_links,omitempty"`
|
||||
}
|
||||
|
||||
type hypervisorLink struct {
|
||||
HREF string `json:"href"`
|
||||
Rel string `json:"rel,omitempty"`
|
||||
}
|
||||
|
||||
type hypervisor struct {
|
||||
|
|
|
@ -8,27 +8,35 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_parseHypervisorDetail(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseHypervisorDetail_Failure(t *testing.T) {
|
||||
f := func(data string) {
|
||||
t.Helper()
|
||||
|
||||
_, err := parseHypervisorDetail([]byte(data))
|
||||
if err == nil {
|
||||
t.Fatalf("expecting non-nil error")
|
||||
}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want hypervisorDetail
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "bad data",
|
||||
args: args{
|
||||
data: []byte(`{ff}`),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "1 hypervisor",
|
||||
args: args{
|
||||
data: []byte(`{
|
||||
|
||||
// bad data
|
||||
f(`{ff}`)
|
||||
}
|
||||
|
||||
func TestParseHypervisorDetail_Success(t *testing.T) {
|
||||
f := func(data string, resultExpected *hypervisorDetail) {
|
||||
t.Helper()
|
||||
|
||||
result, err := parseHypervisorDetail([]byte(data))
|
||||
if err != nil {
|
||||
t.Fatalf("parseHypervisorDetail() error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(result, resultExpected) {
|
||||
t.Fatalf("unexpected result\ngot\n%#v\nwant\n%#v", result, resultExpected)
|
||||
}
|
||||
}
|
||||
|
||||
// 1 hypervisor
|
||||
data := `{
|
||||
"hypervisors": [
|
||||
{
|
||||
"cpu_info": {
|
||||
|
@ -69,78 +77,51 @@ func Test_parseHypervisorDetail(t *testing.T) {
|
|||
"vcpus": 2,
|
||||
"vcpus_used": 0
|
||||
}
|
||||
]}`),
|
||||
},
|
||||
want: hypervisorDetail{
|
||||
Hypervisors: []hypervisor{
|
||||
{
|
||||
HostIP: "1.1.1.1",
|
||||
ID: 2,
|
||||
Hostname: "host1",
|
||||
Status: "enabled",
|
||||
State: "up",
|
||||
Type: "fake",
|
||||
},
|
||||
},
|
||||
]}`
|
||||
|
||||
resultExpected := &hypervisorDetail{
|
||||
Hypervisors: []hypervisor{
|
||||
{
|
||||
HostIP: "1.1.1.1",
|
||||
ID: 2,
|
||||
Hostname: "host1",
|
||||
Status: "enabled",
|
||||
State: "up",
|
||||
Type: "fake",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, resultExpected)
|
||||
}
|
||||
|
||||
func Test_addHypervisorLabels(t *testing.T) {
|
||||
type args struct {
|
||||
hvs []hypervisor
|
||||
port int
|
||||
func TestAddHypervisorLabels(t *testing.T) {
|
||||
f := func(hvs []hypervisor, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addHypervisorLabels(hvs, 9100)
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
hvs := []hypervisor{
|
||||
{
|
||||
name: "",
|
||||
args: args{
|
||||
port: 9100,
|
||||
hvs: []hypervisor{
|
||||
{
|
||||
Type: "fake",
|
||||
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",
|
||||
}),
|
||||
},
|
||||
Type: "fake",
|
||||
ID: 5,
|
||||
State: "enabled",
|
||||
Status: "up",
|
||||
Hostname: "fakehost",
|
||||
HostIP: "1.2.2.2",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addHypervisorLabels(tt.args.hvs, tt.args.port)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
labelssExpected := []*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",
|
||||
}),
|
||||
}
|
||||
f(hvs, labelssExpected)
|
||||
}
|
||||
|
|
|
@ -14,28 +14,34 @@ import (
|
|||
// See https://docs.openstack.org/api-ref/compute/#list-servers
|
||||
type serversDetail struct {
|
||||
Servers []server `json:"servers"`
|
||||
Links []struct {
|
||||
HREF string `json:"href"`
|
||||
Rel string `json:"rel"`
|
||||
} `json:"servers_links,omitempty"`
|
||||
Links []link `json:"servers_links,omitempty"`
|
||||
}
|
||||
|
||||
type link struct {
|
||||
HREF string `json:"href"`
|
||||
Rel string `json:"rel"`
|
||||
}
|
||||
|
||||
type server struct {
|
||||
ID string `json:"id"`
|
||||
TenantID string `json:"tenant_id"`
|
||||
UserID string `json:"user_id"`
|
||||
Name string `json:"name"`
|
||||
HostID string `json:"hostid"`
|
||||
Status string `json:"status"`
|
||||
Addresses map[string][]struct {
|
||||
Address string `json:"addr"`
|
||||
Version int `json:"version"`
|
||||
Type string `json:"OS-EXT-IPS:type"`
|
||||
} `json:"addresses"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
Flavor struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"flavor"`
|
||||
ID string `json:"id"`
|
||||
TenantID string `json:"tenant_id"`
|
||||
UserID string `json:"user_id"`
|
||||
Name string `json:"name"`
|
||||
HostID string `json:"hostid"`
|
||||
Status string `json:"status"`
|
||||
Addresses map[string][]serverAddress `json:"addresses"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
Flavor serverFlavor `json:"flavor"`
|
||||
}
|
||||
|
||||
type serverAddress struct {
|
||||
Address string `json:"addr"`
|
||||
Version int `json:"version"`
|
||||
Type string `json:"OS-EXT-IPS:type"`
|
||||
}
|
||||
|
||||
type serverFlavor struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func parseServersDetail(data []byte) (*serversDetail, error) {
|
||||
|
|
|
@ -8,159 +8,133 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_addInstanceLabels(t *testing.T) {
|
||||
type args struct {
|
||||
servers []server
|
||||
port int
|
||||
func TestAddInstanceLabels(t *testing.T) {
|
||||
f := func(servers []server, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addInstanceLabels(servers, 9100)
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// empty response
|
||||
f(nil, nil)
|
||||
|
||||
// one server
|
||||
servers := []server{
|
||||
{
|
||||
name: "empty_response",
|
||||
args: args{
|
||||
port: 9100,
|
||||
ID: "10",
|
||||
Status: "enabled",
|
||||
Name: "server-1",
|
||||
HostID: "some-host-id",
|
||||
TenantID: "some-tenant-id",
|
||||
UserID: "some-user-id",
|
||||
Flavor: serverFlavor{
|
||||
ID: "5",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "one_server",
|
||||
args: args{
|
||||
port: 9100,
|
||||
servers: []server{
|
||||
Addresses: map[string][]serverAddress{
|
||||
"test": {
|
||||
{
|
||||
ID: "10",
|
||||
Status: "enabled",
|
||||
Name: "server-1",
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
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",
|
||||
args: args{
|
||||
port: 9100,
|
||||
servers: []server{
|
||||
ID: "10",
|
||||
Status: "enabled",
|
||||
Name: "server-2",
|
||||
HostID: "some-host-id",
|
||||
TenantID: "some-tenant-id",
|
||||
UserID: "some-user-id",
|
||||
Flavor: serverFlavor{
|
||||
ID: "5",
|
||||
},
|
||||
Addresses: map[string][]serverAddress{
|
||||
"test": {
|
||||
{
|
||||
ID: "10",
|
||||
Status: "enabled",
|
||||
Name: "server-2",
|
||||
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",
|
||||
},
|
||||
{
|
||||
Address: "1.5.5.5",
|
||||
Version: 4,
|
||||
Type: "floating",
|
||||
},
|
||||
},
|
||||
"internal": {
|
||||
{
|
||||
Address: "10.10.0.1",
|
||||
Version: 4,
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addInstanceLabels(tt.args.servers, tt.args.port)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
labelssExpected = []*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",
|
||||
}),
|
||||
}
|
||||
f(servers, labelssExpected)
|
||||
}
|
||||
|
||||
func Test_parseServersDetail(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
func TestParseServersDetail(t *testing.T) {
|
||||
f := func(data string, resultExpected *serversDetail) {
|
||||
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
|
||||
args args
|
||||
want serversDetail
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "parse ok",
|
||||
args: args{
|
||||
data: []byte(`{
|
||||
|
||||
// parse ok
|
||||
data := `{
|
||||
"servers":[
|
||||
{
|
||||
"id":"c9f68076-01a3-489a-aebe-8b773c71e7f3",
|
||||
|
@ -210,54 +184,36 @@ func Test_parseServersDetail(t *testing.T) {
|
|||
]
|
||||
}
|
||||
]
|
||||
}`),
|
||||
},
|
||||
want: serversDetail{
|
||||
Servers: []server{
|
||||
{
|
||||
Flavor: struct {
|
||||
ID string `json:"id"`
|
||||
}{ID: "1"},
|
||||
ID: "c9f68076-01a3-489a-aebe-8b773c71e7f3",
|
||||
TenantID: "d34be4e44f9c444eab9a5ec7b953951f",
|
||||
UserID: "e55737f142ac42f18093037760656bd7",
|
||||
Name: "test10",
|
||||
HostID: "e26db8db23736877aa92ebbbe11743b2a2a3b107aada00a8a0cf474b",
|
||||
Status: "ACTIVE",
|
||||
Metadata: map[string]string{},
|
||||
Addresses: map[string][]struct {
|
||||
Address string `json:"addr"`
|
||||
Version int `json:"version"`
|
||||
Type string `json:"OS-EXT-IPS:type"`
|
||||
}{
|
||||
"test": {
|
||||
{
|
||||
Address: "192.168.222.15",
|
||||
Version: 4,
|
||||
Type: "fixed",
|
||||
},
|
||||
{
|
||||
Address: "10.20.20.69",
|
||||
Version: 4,
|
||||
Type: "floating",
|
||||
},
|
||||
},
|
||||
}`
|
||||
resultExpected := &serversDetail{
|
||||
Servers: []server{
|
||||
{
|
||||
Flavor: serverFlavor{
|
||||
ID: "1",
|
||||
},
|
||||
ID: "c9f68076-01a3-489a-aebe-8b773c71e7f3",
|
||||
TenantID: "d34be4e44f9c444eab9a5ec7b953951f",
|
||||
UserID: "e55737f142ac42f18093037760656bd7",
|
||||
Name: "test10",
|
||||
HostID: "e26db8db23736877aa92ebbbe11743b2a2a3b107aada00a8a0cf474b",
|
||||
Status: "ACTIVE",
|
||||
Metadata: map[string]string{},
|
||||
Addresses: map[string][]serverAddress{
|
||||
"test": {
|
||||
{
|
||||
Address: "192.168.222.15",
|
||||
Version: 4,
|
||||
Type: "fixed",
|
||||
},
|
||||
{
|
||||
Address: "10.20.20.69",
|
||||
Version: 4,
|
||||
Type: "floating",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
f(data, resultExpected)
|
||||
}
|
||||
|
|
|
@ -7,169 +7,157 @@ import (
|
|||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
||||
)
|
||||
|
||||
func Test_addInstanceLabels(t *testing.T) {
|
||||
type args struct {
|
||||
instances []instance
|
||||
func TestAddInstanceLabels(t *testing.T) {
|
||||
f := func(instances []instance, labelssExpected []*promutils.Labels) {
|
||||
t.Helper()
|
||||
|
||||
labelss := addInstanceLabels(instances)
|
||||
discoveryutils.TestEqualLabelss(t, labelss, labelssExpected)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*promutils.Labels
|
||||
}{
|
||||
|
||||
// empty response
|
||||
f(nil, nil)
|
||||
|
||||
// one server
|
||||
instances := []instance{
|
||||
{
|
||||
name: "empty_response",
|
||||
args: args{},
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
},
|
||||
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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := addInstanceLabels(tt.args.instances)
|
||||
discoveryutils.TestEqualLabelss(t, got, tt.want)
|
||||
})
|
||||
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",
|
||||
"__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) {
|
||||
allowed := true
|
||||
notAllowed := false
|
||||
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",
|
||||
},
|
||||
}
|
||||
f := func(h func(w http.ResponseWriter, r *http.Request), httpCfg *promauth.HTTPClientConfig, expectedMessage string) {
|
||||
t.Helper()
|
||||
|
||||
for _, validConfig := range newClientValidConfig {
|
||||
testServer, err := newTestServer(validConfig.handler)
|
||||
s, err := newTestServer(h)
|
||||
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 {
|
||||
t.Errorf("Can't create a client from this config: %+v", validConfig.httpCfg)
|
||||
continue
|
||||
t.Fatalf("can't create a client from this config: %+v", httpCfg)
|
||||
}
|
||||
|
||||
response, err := client.client.client.Get(testServer.URL)
|
||||
response, err := client.client.client.Get(s.URL)
|
||||
if err != nil {
|
||||
t.Errorf("Can't connect to the test server using this config: %+v: %v", validConfig.httpCfg, err)
|
||||
continue
|
||||
t.Fatalf("can't connect to the test server using this config: %+v: %v", httpCfg, err)
|
||||
}
|
||||
|
||||
message, err := io.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Can't read the server response body using this config: %+v", validConfig.httpCfg)
|
||||
continue
|
||||
t.Fatalf("Can't read the server response body using this config: %+v", httpCfg)
|
||||
}
|
||||
|
||||
trimMessage := strings.TrimSpace(string(message))
|
||||
if validConfig.expectedMessage != trimMessage {
|
||||
t.Errorf("The expected message (%s) differs from the obtained message (%s) using this config: %+v",
|
||||
validConfig.expectedMessage, trimMessage, validConfig.httpCfg)
|
||||
if expectedMessage != trimMessage {
|
||||
t.Fatalf("The expected message (%s) differs from the obtained message (%s) using this config: %+v", expectedMessage, trimMessage, 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"
|
||||
)
|
||||
|
||||
func Test_streamContext_Read(t *testing.T) {
|
||||
func TestStreamContextRead(t *testing.T) {
|
||||
f := func(s string, rowsExpected *graphite.Rows) {
|
||||
t.Helper()
|
||||
ctx := getStreamContext(strings.NewReader(s))
|
||||
|
|
|
@ -4,53 +4,45 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func Test_Validate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
snapshotName string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
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)
|
||||
}
|
||||
})
|
||||
func TestValidate_Failure(t *testing.T) {
|
||||
f := func(snapshotName string) {
|
||||
t.Helper()
|
||||
|
||||
err := Validate(snapshotName)
|
||||
if err == nil {
|
||||
t.Fatalf("expecting non-nil error")
|
||||
}
|
||||
}
|
||||
|
||||
// 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