diff --git a/lib/httpserver/httpserver_test.go b/lib/httpserver/httpserver_test.go index 5c36e3488..198cfffa4 100644 --- a/lib/httpserver/httpserver_test.go +++ b/lib/httpserver/httpserver_test.go @@ -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) } } diff --git a/lib/httputils/tls_test.go b/lib/httputils/tls_test.go index 8374f5790..a27669e0b 100644 --- a/lib/httputils/tls_test.go +++ b/lib/httputils/tls_test.go @@ -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") } } diff --git a/lib/logstorage/tenant_id_test.go b/lib/logstorage/tenant_id_test.go index f440e5d8e..60bb34fd8 100644 --- a/lib/logstorage/tenant_id_test.go +++ b/lib/logstorage/tenant_id_test.go @@ -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() { diff --git a/lib/promscrape/discovery/digitalocean/api_test.go b/lib/promscrape/discovery/digitalocean/api_test.go index f9833e4f6..abc6f1bfb 100644 --- a/lib/promscrape/discovery/digitalocean/api_test.go +++ b/lib/promscrape/discovery/digitalocean/api_test.go @@ -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) } diff --git a/lib/promscrape/discovery/digitalocean/digitalocean.go b/lib/promscrape/discovery/digitalocean/digitalocean.go index 61690d35b..b0a716f50 100644 --- a/lib/promscrape/discovery/digitalocean/digitalocean.go +++ b/lib/promscrape/discovery/digitalocean/digitalocean.go @@ -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) { diff --git a/lib/promscrape/discovery/digitalocean/digitalocean_test.go b/lib/promscrape/discovery/digitalocean/digitalocean_test.go index 05d0b5f0f..f1cd1d893 100644 --- a/lib/promscrape/discovery/digitalocean/digitalocean_test.go +++ b/lib/promscrape/discovery/digitalocean/digitalocean_test.go @@ -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) } diff --git a/lib/promscrape/discovery/docker/container.go b/lib/promscrape/discovery/docker/container.go index 512ab212d..1875efbd5 100644 --- a/lib/promscrape/discovery/docker/container.go +++ b/lib/promscrape/discovery/docker/container.go @@ -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) { diff --git a/lib/promscrape/discovery/docker/container_test.go b/lib/promscrape/discovery/docker/container_test.go index 7d4f45d95..19cf2dcce 100644 --- a/lib/promscrape/discovery/docker/container_test.go +++ b/lib/promscrape/discovery/docker/container_test.go @@ -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) } diff --git a/lib/promscrape/discovery/docker/network_test.go b/lib/promscrape/discovery/docker/network_test.go index 6d2996a17..61c7e5b21 100644 --- a/lib/promscrape/discovery/docker/network_test.go +++ b/lib/promscrape/discovery/docker/network_test.go @@ -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) } diff --git a/lib/promscrape/discovery/dockerswarm/network_test.go b/lib/promscrape/discovery/dockerswarm/network_test.go index d274cca61..a66ad2f19 100644 --- a/lib/promscrape/discovery/dockerswarm/network_test.go +++ b/lib/promscrape/discovery/dockerswarm/network_test.go @@ -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) } diff --git a/lib/promscrape/discovery/dockerswarm/nodes.go b/lib/promscrape/discovery/dockerswarm/nodes.go index 1e3ea0801..b59836aa3 100644 --- a/lib/promscrape/discovery/dockerswarm/nodes.go +++ b/lib/promscrape/discovery/dockerswarm/nodes.go @@ -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) { diff --git a/lib/promscrape/discovery/dockerswarm/nodes_test.go b/lib/promscrape/discovery/dockerswarm/nodes_test.go index a3ceda39d..a75ef570f 100644 --- a/lib/promscrape/discovery/dockerswarm/nodes_test.go +++ b/lib/promscrape/discovery/dockerswarm/nodes_test.go @@ -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) } diff --git a/lib/promscrape/discovery/dockerswarm/services.go b/lib/promscrape/discovery/dockerswarm/services.go index 88846671b..f82fadb13 100644 --- a/lib/promscrape/discovery/dockerswarm/services.go +++ b/lib/promscrape/discovery/dockerswarm/services.go @@ -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 { diff --git a/lib/promscrape/discovery/dockerswarm/services_test.go b/lib/promscrape/discovery/dockerswarm/services_test.go index 82709b77f..12d804365 100644 --- a/lib/promscrape/discovery/dockerswarm/services_test.go +++ b/lib/promscrape/discovery/dockerswarm/services_test.go @@ -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) } diff --git a/lib/promscrape/discovery/dockerswarm/tasks.go b/lib/promscrape/discovery/dockerswarm/tasks.go index 6eec2e14d..32f930bff 100644 --- a/lib/promscrape/discovery/dockerswarm/tasks.go +++ b/lib/promscrape/discovery/dockerswarm/tasks.go @@ -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) { diff --git a/lib/promscrape/discovery/dockerswarm/tasks_test.go b/lib/promscrape/discovery/dockerswarm/tasks_test.go index fadabcd5d..3641d6024 100644 --- a/lib/promscrape/discovery/dockerswarm/tasks_test.go +++ b/lib/promscrape/discovery/dockerswarm/tasks_test.go @@ -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) } diff --git a/lib/promscrape/discovery/eureka/api_test.go b/lib/promscrape/discovery/eureka/api_test.go index 648476e22..b01f72aab 100644 --- a/lib/promscrape/discovery/eureka/api_test.go +++ b/lib/promscrape/discovery/eureka/api_test.go @@ -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(` + + // parse ok 1 app with instance + data := ` 1 UP_1_ @@ -55,53 +56,40 @@ func Test_parseAPIResponse(t *testing.T) { ADDED -`), - }, - want: &applications{ - Applications: []Application{ +` + + 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) } diff --git a/lib/promscrape/discovery/eureka/eureka_test.go b/lib/promscrape/discovery/eureka/eureka_test.go index 290064096..c9b8917c6 100644 --- a/lib/promscrape/discovery/eureka/eureka_test.go +++ b/lib/promscrape/discovery/eureka/eureka_test.go @@ -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) } diff --git a/lib/promscrape/discovery/http/api_test.go b/lib/promscrape/discovery/http/api_test.go index eb33d3cc2..72e389e06 100644 --- a/lib/promscrape/discovery/http/api_test.go +++ b/lib/promscrape/discovery/http/api_test.go @@ -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) } diff --git a/lib/promscrape/discovery/http/http_test.go b/lib/promscrape/discovery/http/http_test.go index 444571bd9..2dcad1d53 100644 --- a/lib/promscrape/discovery/http/http_test.go +++ b/lib/promscrape/discovery/http/http_test.go @@ -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) } diff --git a/lib/promscrape/discovery/kubernetes/api_watcher.go b/lib/promscrape/discovery/kubernetes/api_watcher.go index 4914f4cec..1160f409d 100644 --- a/lib/promscrape/discovery/kubernetes/api_watcher.go +++ b/lib/promscrape/discovery/kubernetes/api_watcher.go @@ -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) { diff --git a/lib/promscrape/discovery/kubernetes/endpointslice_test.go b/lib/promscrape/discovery/kubernetes/endpointslice_test.go index 7a15c0b3b..1d8d10a70 100644 --- a/lib/promscrape/discovery/kubernetes/endpointslice_test.go +++ b/lib/promscrape/discovery/kubernetes/endpointslice_test.go @@ -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 { diff --git a/lib/promscrape/discovery/kubernetes/kubeconfig.go b/lib/promscrape/discovery/kubernetes/kubeconfig.go index a37685c49..aa405beed 100644 --- a/lib/promscrape/discovery/kubernetes/kubeconfig.go +++ b/lib/promscrape/discovery/kubernetes/kubeconfig.go @@ -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 diff --git a/lib/promscrape/discovery/kuma/api.go b/lib/promscrape/discovery/kuma/api.go index fa27ad6d1..3695dba24 100644 --- a/lib/promscrape/discovery/kuma/api.go +++ b/lib/promscrape/discovery/kuma/api.go @@ -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"` } diff --git a/lib/promscrape/discovery/nomad/service.go b/lib/promscrape/discovery/nomad/service.go index 1dc48b17e..2580b8162 100644 --- a/lib/promscrape/discovery/nomad/service.go +++ b/lib/promscrape/discovery/nomad/service.go @@ -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. diff --git a/lib/promscrape/discovery/openstack/auth.go b/lib/promscrape/discovery/openstack/auth.go index e80745c49..b26afbf91 100644 --- a/lib/promscrape/discovery/openstack/auth.go +++ b/lib/promscrape/discovery/openstack/auth.go @@ -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 { diff --git a/lib/promscrape/discovery/openstack/auth_test.go b/lib/promscrape/discovery/openstack/auth_test.go index 9657bd36e..f5c4b4cae 100644 --- a/lib/promscrape/discovery/openstack/auth_test.go +++ b/lib/promscrape/discovery/openstack/auth_test.go @@ -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) } diff --git a/lib/promscrape/discovery/openstack/hypervisor.go b/lib/promscrape/discovery/openstack/hypervisor.go index 04c0d9dc6..12150f43d 100644 --- a/lib/promscrape/discovery/openstack/hypervisor.go +++ b/lib/promscrape/discovery/openstack/hypervisor.go @@ -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 { diff --git a/lib/promscrape/discovery/openstack/hypervisor_test.go b/lib/promscrape/discovery/openstack/hypervisor_test.go index 12f6a0ad1..d867d30e4 100644 --- a/lib/promscrape/discovery/openstack/hypervisor_test.go +++ b/lib/promscrape/discovery/openstack/hypervisor_test.go @@ -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) } diff --git a/lib/promscrape/discovery/openstack/instance.go b/lib/promscrape/discovery/openstack/instance.go index 06c338aad..e1281217d 100644 --- a/lib/promscrape/discovery/openstack/instance.go +++ b/lib/promscrape/discovery/openstack/instance.go @@ -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) { diff --git a/lib/promscrape/discovery/openstack/instance_test.go b/lib/promscrape/discovery/openstack/instance_test.go index 7a5e34ccd..709fb358a 100644 --- a/lib/promscrape/discovery/openstack/instance_test.go +++ b/lib/promscrape/discovery/openstack/instance_test.go @@ -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) } diff --git a/lib/promscrape/discovery/yandexcloud/instance_test.go b/lib/promscrape/discovery/yandexcloud/instance_test.go index d9161cfc9..ecaf5cdf0 100644 --- a/lib/promscrape/discovery/yandexcloud/instance_test.go +++ b/lib/promscrape/discovery/yandexcloud/instance_test.go @@ -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) } diff --git a/lib/promscrape/discoveryutils/client_test.go b/lib/promscrape/discoveryutils/client_test.go index 860ce124a..4ff592ffe 100644 --- a/lib/promscrape/discoveryutils/client_test.go +++ b/lib/promscrape/discoveryutils/client_test.go @@ -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") } diff --git a/lib/protoparser/graphite/stream/streamparser_test.go b/lib/protoparser/graphite/stream/streamparser_test.go index 416473b62..6caee9f87 100644 --- a/lib/protoparser/graphite/stream/streamparser_test.go +++ b/lib/protoparser/graphite/stream/streamparser_test.go @@ -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)) diff --git a/lib/snapshot/snapshotutil/snapshotutil_test.go b/lib/snapshot/snapshotutil/snapshotutil_test.go index 5c2a3d5a0..5946bc535 100644 --- a/lib/snapshot/snapshotutil/snapshotutil_test.go +++ b/lib/snapshot/snapshotutil/snapshotutil_test.go @@ -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") }