diff --git a/discovery/vultr/mock_test.go b/discovery/vultr/mock_test.go index bfc24d06f..984e70845 100644 --- a/discovery/vultr/mock_test.go +++ b/discovery/vultr/mock_test.go @@ -168,3 +168,111 @@ func (m *SDMock) HandleInstanceList() { `) }) } + +// HandleBaremetalList mocks vultr baremetal list. +func (m *SDMock) HandleBaremetalList() { + m.Mux.HandleFunc("/v2/bare-metals", func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") != fmt.Sprintf("Bearer %s", APIKey) { + w.WriteHeader(http.StatusForbidden) + return + } + + w.Header().Add("content-type", "application/json; charset=utf-8") + w.WriteHeader(http.StatusOK) + + fmt.Fprint(w, ` +{ + "bare_metals": [ + { + "id": "cb676a46-66fd-4dfb-b839-443f2e6c0b60", + "os": "Application", + "ram": "32768 MB", + "disk": "2x 240GB SSD", + "main_ip": "192.0.2.123", + "cpu_count": 4, + "region": "ams", + "default_password": "example-password", + "date_created": "2020-10-10T01:56:20+00:00", + "status": "active", + "netmask_v4": "255.255.254.0", + "gateway_v4": "192.0.2.1", + "plan": "vbm-4c-32gb", + "v6_network": "2001:0db8:5001:3990::", + "v6_main_ip": "2001:0db8:5001:3990:0ec4:7aff:fe8e:f97a", + "v6_network_size": 64, + "label": "Example Bare Metal", + "mac_address": 2199756823533, + "os_id": 186, + "app_id": 3, + "image_id": "", + "features": ["backups"], + "tags": ["tag1", "tag2", "tag3"], + "user_scheme": "root", + "mdisk_mode": "raid1" + }, + { + "id": "sdfgsdfgsdfg-66fd-4dfb-b839-443f2e6c0b60", + "os": "Application", + "ram": "32768 MB", + "disk": "2x 240GB SSD", + "main_ip": "192.0.2.124", + "cpu_count": 4, + "region": "ams", + "default_password": "example-password", + "date_created": "2020-10-10T01:56:20+00:00", + "status": "active", + "netmask_v4": "255.255.254.0", + "gateway_v4": "192.0.2.1", + "plan": "vbm-4c-32gb", + "v6_network": "2001:0db8:5001:3990::", + "v6_main_ip": "2001:0db8:5001:3990:0ec4:7aff:fe8e:f97a", + "v6_network_size": 64, + "label": "Example Bare Metal 2", + "mac_address": 2199756823533, + "os_id": 186, + "app_id": 3, + "image_id": "", + "features": ["backups"], + "tags": ["tag1", "tag2", "tag3"], + "user_scheme": "root", + "mdisk_mode": "raid1" + }, + { + "id": "wertwery6-66fd-4dfb-b839-443f2e6c0b60", + "os": "Application", + "ram": "32768 MB", + "disk": "2x 240GB SSD", + "main_ip": "192.0.2.125", + "cpu_count": 4, + "region": "ams", + "default_password": "example-password", + "date_created": "2020-10-10T01:56:20+00:00", + "status": "active", + "netmask_v4": "255.255.254.0", + "gateway_v4": "192.0.2.1", + "plan": "vbm-4c-32gb", + "v6_network": "2001:0db8:5001:3990::", + "v6_main_ip": "2001:0db8:5001:3990:0ec4:7aff:fe8e:f97a", + "v6_network_size": 64, + "label": "Example Bare Metal 3", + "mac_address": 2199756823533, + "os_id": 186, + "app_id": 3, + "image_id": "", + "features": ["backups"], + "tags": ["tag1", "tag2", "tag3"], + "user_scheme": "root", + "mdisk_mode": "raid1" + } + ], + "meta": { + "total": 3, + "links": { + "next": "", + "prev": "" + } + } +} +`) + }) +} diff --git a/discovery/vultr/vultr.go b/discovery/vultr/vultr.go index ee92f0169..e5eff4e4e 100644 --- a/discovery/vultr/vultr.go +++ b/discovery/vultr/vultr.go @@ -54,7 +54,27 @@ const ( vultrInstanceLabelMemory = vultrInstanceLabel + "ram_mb" vultrInstanceLabelBandwidth = vultrInstanceLabel + "allowed_bandwidth_gb" vultrInstanceLabelDisk = vultrInstanceLabel + "disk_gb" - separator = "," + + vultrBaremetalLabel = model.MetaLabelPrefix + "vultr_baremetal_" + vultrBaremetalLabelID = vultrBaremetalLabel + "id" + vultrBaremetalLabelLabel = vultrBaremetalLabel + "label" + vultrBaremetalLabelOS = vultrBaremetalLabel + "os" + vultrBaremetalLabelOSID = vultrBaremetalLabel + "os_id" + vultrBaremetalLabelAppID = vultrBaremetalLabel + "app_id" + vultrBaremetalLabelImageID = vultrBaremetalLabel + "image_id" + vultrBaremetalLabelRegion = vultrBaremetalLabel + "region" + vultrBaremetalLabelPlan = vultrBaremetalLabel + "plan" + vultrBaremetalLabelMainIP = vultrBaremetalLabel + "main_ip" + vultrBaremetalLabelMainIPv6 = vultrBaremetalLabel + "main_ipv6" + vultrBaremetalLabelNetmaskv4 = vultrBaremetalLabel + "netmask_v4" + vultrBaremetalLabelGatewayv4 = vultrBaremetalLabel + "gateway_v4" + vultrBaremetalLabelFeatures = vultrBaremetalLabel + "features" + vultrBaremetalLabelTags = vultrBaremetalLabel + "tags" + vultrBaremetalLabelServerStatus = vultrBaremetalLabel + "server_status" + vultrBaremetalLabelCPU = vultrBaremetalLabel + "cpu_count" + vultrBaremetalLabelMemory = vultrBaremetalLabel + "ram_mb" + vultrBaremetalLabelDisk = vultrBaremetalLabel + "disk_gb" + separator = "," ) // DefaultSDConfig is the default Vultr SD configuration. @@ -200,6 +220,49 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) { tg.Targets = append(tg.Targets, labels) } + baremetals, err := d.listBaremetals(ctx) + if err != nil { + return nil, err + } + + for _, baremetal := range baremetals { + labels := model.LabelSet{ + vultrBaremetalLabelLabel: model.LabelValue(baremetal.Label), + vultrBaremetalLabelID: model.LabelValue(baremetal.ID), + vultrBaremetalLabelOS: model.LabelValue(baremetal.Os), + vultrBaremetalLabelOSID: model.LabelValue(strconv.Itoa(baremetal.OsID)), + vultrBaremetalLabelAppID: model.LabelValue(strconv.Itoa(baremetal.AppID)), + vultrBaremetalLabelImageID: model.LabelValue(baremetal.ImageID), + vultrBaremetalLabelRegion: model.LabelValue(baremetal.Region), + vultrBaremetalLabelPlan: model.LabelValue(baremetal.Plan), + vultrBaremetalLabelMainIP: model.LabelValue(baremetal.MainIP), + vultrBaremetalLabelMainIPv6: model.LabelValue(baremetal.V6MainIP), + vultrBaremetalLabelNetmaskv4: model.LabelValue(baremetal.NetmaskV4), + vultrBaremetalLabelGatewayv4: model.LabelValue(baremetal.GatewayV4), + vultrBaremetalLabelServerStatus: model.LabelValue(baremetal.Status), + vultrBaremetalLabelCPU: model.LabelValue(strconv.Itoa(baremetal.CPUCount)), + vultrBaremetalLabelMemory: model.LabelValue(baremetal.RAM), + vultrBaremetalLabelDisk: model.LabelValue(baremetal.Disk), + } + + addr := net.JoinHostPort(baremetal.MainIP, strconv.FormatUint(uint64(d.port), 10)) + labels[model.AddressLabel] = model.LabelValue(addr) + + // We surround the separated list with the separator as well. This way regular expressions + // in relabeling rules don't have to consider feature positions. + if len(baremetal.Features) > 0 { + features := separator + strings.Join(baremetal.Features, separator) + separator + labels[vultrBaremetalLabelFeatures] = model.LabelValue(features) + } + + if len(baremetal.Tags) > 0 { + tags := separator + strings.Join(baremetal.Tags, separator) + separator + labels[vultrBaremetalLabelTags] = model.LabelValue(tags) + } + + tg.Targets = append(tg.Targets, labels) + } + return []*targetgroup.Group{tg}, nil } @@ -225,3 +288,26 @@ func (d *Discovery) listInstances(ctx context.Context) ([]govultr.Instance, erro return instances, nil } + +func (d *Discovery) listBaremetals(ctx context.Context) ([]govultr.BareMetalServer, error) { + var baremetals []govultr.BareMetalServer + + listOptions := &govultr.ListOptions{ + PerPage: 100, + } + + for { + pagedBaremetals, meta, err := d.client.BareMetalServer.List(ctx, listOptions) + if err != nil { + return nil, err + } + baremetals = append(baremetals, pagedBaremetals...) + + if meta.Links.Next == "" { + break + } + listOptions.Cursor = meta.Links.Next + } + + return baremetals, nil +} diff --git a/discovery/vultr/vultr_test.go b/discovery/vultr/vultr_test.go index 00ef21e38..3b8f548fb 100644 --- a/discovery/vultr/vultr_test.go +++ b/discovery/vultr/vultr_test.go @@ -40,6 +40,7 @@ func (s *VultrSDTestSuite) SetupTest(t *testing.T) { s.Mock.Setup() s.Mock.HandleInstanceList() + s.Mock.HandleBaremetalList() } func TestVultrSDRefresh(t *testing.T) { @@ -72,7 +73,7 @@ func TestVultrSDRefresh(t *testing.T) { tg := tgs[0] require.NotNil(t, tg) require.NotNil(t, tg.Targets) - require.Len(t, tg.Targets, 3) + require.Len(t, tg.Targets, 6) for i, k := range []model.LabelSet{ { @@ -131,6 +132,69 @@ func TestVultrSDRefresh(t *testing.T) { "__meta_vultr_instance_disk_gb": model.LabelValue("128"), "__meta_vultr_instance_allowed_bandwidth_gb": model.LabelValue("3000"), }, + { + "__address__": model.LabelValue("192.0.2.123:80"), + "__meta_vultr_baremetal_id": model.LabelValue("cb676a46-66fd-4dfb-b839-443f2e6c0b60"), + "__meta_vultr_baremetal_label": model.LabelValue("Example Bare Metal"), + "__meta_vultr_baremetal_os": model.LabelValue("Application"), + "__meta_vultr_baremetal_ram_mb": model.LabelValue("32768 MB"), + "__meta_vultr_baremetal_disk_gb": model.LabelValue("2x 240GB SSD"), + "__meta_vultr_baremetal_main_ip": model.LabelValue("192.0.2.123"), + "__meta_vultr_baremetal_cpu_count": model.LabelValue("4"), + "__meta_vultr_baremetal_region": model.LabelValue("ams"), + "__meta_vultr_baremetal_plan": model.LabelValue("vbm-4c-32gb"), + "__meta_vultr_baremetal_server_status": model.LabelValue("active"), + "__meta_vultr_baremetal_netmask_v4": model.LabelValue("255.255.254.0"), + "__meta_vultr_baremetal_gateway_v4": model.LabelValue("192.0.2.1"), + "__meta_vultr_baremetal_main_ipv6": model.LabelValue("2001:0db8:5001:3990:0ec4:7aff:fe8e:f97a"), + "__meta_vultr_baremetal_os_id": model.LabelValue("186"), + "__meta_vultr_baremetal_app_id": model.LabelValue("3"), + "__meta_vultr_baremetal_image_id": model.LabelValue(""), + "__meta_vultr_baremetal_features": model.LabelValue(",backups,"), + "__meta_vultr_baremetal_tags": model.LabelValue(",tag1,tag2,tag3,"), + }, + { + "__address__": model.LabelValue("192.0.2.124:80"), + "__meta_vultr_baremetal_id": model.LabelValue("sdfgsdfgsdfg-66fd-4dfb-b839-443f2e6c0b60"), + "__meta_vultr_baremetal_label": model.LabelValue("Example Bare Metal 2"), + "__meta_vultr_baremetal_os": model.LabelValue("Application"), + "__meta_vultr_baremetal_ram_mb": model.LabelValue("32768 MB"), + "__meta_vultr_baremetal_disk_gb": model.LabelValue("2x 240GB SSD"), + "__meta_vultr_baremetal_main_ip": model.LabelValue("192.0.2.124"), + "__meta_vultr_baremetal_cpu_count": model.LabelValue("4"), + "__meta_vultr_baremetal_region": model.LabelValue("ams"), + "__meta_vultr_baremetal_plan": model.LabelValue("vbm-4c-32gb"), + "__meta_vultr_baremetal_server_status": model.LabelValue("active"), + "__meta_vultr_baremetal_netmask_v4": model.LabelValue("255.255.254.0"), + "__meta_vultr_baremetal_gateway_v4": model.LabelValue("192.0.2.1"), + "__meta_vultr_baremetal_main_ipv6": model.LabelValue("2001:0db8:5001:3990:0ec4:7aff:fe8e:f97a"), + "__meta_vultr_baremetal_os_id": model.LabelValue("186"), + "__meta_vultr_baremetal_app_id": model.LabelValue("3"), + "__meta_vultr_baremetal_image_id": model.LabelValue(""), + "__meta_vultr_baremetal_features": model.LabelValue(",backups,"), + "__meta_vultr_baremetal_tags": model.LabelValue(",tag1,tag2,tag3,"), + }, + { + "__address__": model.LabelValue("192.0.2.125:80"), + "__meta_vultr_baremetal_id": model.LabelValue("wertwery6-66fd-4dfb-b839-443f2e6c0b60"), + "__meta_vultr_baremetal_label": model.LabelValue("Example Bare Metal 3"), + "__meta_vultr_baremetal_os": model.LabelValue("Application"), + "__meta_vultr_baremetal_ram_mb": model.LabelValue("32768 MB"), + "__meta_vultr_baremetal_disk_gb": model.LabelValue("2x 240GB SSD"), + "__meta_vultr_baremetal_main_ip": model.LabelValue("192.0.2.125"), + "__meta_vultr_baremetal_cpu_count": model.LabelValue("4"), + "__meta_vultr_baremetal_region": model.LabelValue("ams"), + "__meta_vultr_baremetal_plan": model.LabelValue("vbm-4c-32gb"), + "__meta_vultr_baremetal_server_status": model.LabelValue("active"), + "__meta_vultr_baremetal_netmask_v4": model.LabelValue("255.255.254.0"), + "__meta_vultr_baremetal_gateway_v4": model.LabelValue("192.0.2.1"), + "__meta_vultr_baremetal_main_ipv6": model.LabelValue("2001:0db8:5001:3990:0ec4:7aff:fe8e:f97a"), + "__meta_vultr_baremetal_os_id": model.LabelValue("186"), + "__meta_vultr_baremetal_app_id": model.LabelValue("3"), + "__meta_vultr_baremetal_image_id": model.LabelValue(""), + "__meta_vultr_baremetal_features": model.LabelValue(",backups,"), + "__meta_vultr_baremetal_tags": model.LabelValue(",tag1,tag2,tag3,"), + }, } { t.Run(fmt.Sprintf("item %d", i), func(t *testing.T) { require.Equal(t, k, tg.Targets[i]) diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index 2093ed883..993f32470 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -2444,6 +2444,23 @@ The following meta labels are available on targets during [relabeling](#relabel_ * `__meta_vultr_instance_disk_gb` : The size of the disk in GB. * `__meta_vultr_instance_allowed_bandwidth_gb` : Monthly bandwidth quota in GB. +* `__meta_vultr_baremetal_id` : A unique ID for the vultr baremetal +* `__meta_vultr_baremetal_label` : The user-supplied label for this baremetal. +* `__meta_vultr_baremetal_os` : The Operating System name. +* `__meta_vultr_baremetal_os_id` : The Operating System id used by this baremetal. +* `__meta_vultr_baremetal_region` : The Region id where the baremetal is located. +* `__meta_vultr_baremetal_plan` : A unique ID for the Plan. +* `__meta_vultr_baremetal_main_ip` : The main IPv4 address. +* `__meta_vultr_baremetal_main_ipv6` : The main IPv6 address. +* `__meta_vultr_baremetal_features` : List of features that are available to the baremetal. +* `__meta_vultr_baremetal_tags` : List of tags associated with the baremetal. +* `__meta_vultr_baremetal_server_status` : The server health status. +* `__meta_vultr_baremetal_cpu_count` : Number of CPUs. +* `__meta_vultr_baremetal_ram_mb` : The amount of RAM in MB. +* `__meta_vultr_baremetal_netmask_v4` : The netmask for the baremetal. +* `__meta_vultr_baremetal_gateway_v4` : The gateway for the baremetal. +* `__meta_vultr_baremetal_app_id` : The application used to deploy the baremetal. +* `__meta_vultr_baremetal_image_id` : Unique ID of the image used to deploy the baremetal. ```yaml # The port to scrape metrics from. [ port: | default = 80 ]