2024-01-15 09:13:22 +00:00
|
|
|
package hetzner
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
|
|
|
)
|
|
|
|
|
|
|
|
func getRobotServerLabels(cfg *apiConfig) ([]*promutils.Labels, error) {
|
|
|
|
servers, err := getRobotServers(cfg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
var ms []*promutils.Labels
|
2024-01-20 14:52:41 +00:00
|
|
|
for i := range servers {
|
|
|
|
ms = appendRobotTargetLabels(ms, &servers[i], cfg.port)
|
2024-01-15 09:13:22 +00:00
|
|
|
}
|
|
|
|
return ms, nil
|
|
|
|
}
|
|
|
|
|
2024-01-20 14:52:41 +00:00
|
|
|
func appendRobotTargetLabels(ms []*promutils.Labels, server *RobotServer, port int) []*promutils.Labels {
|
|
|
|
m := promutils.NewLabels(16)
|
|
|
|
|
|
|
|
addr := discoveryutils.JoinHostPort(server.ServerIP, port)
|
|
|
|
m.Add("__address__", addr)
|
|
|
|
|
|
|
|
m.Add("__meta_hetzner_role", "robot")
|
|
|
|
m.Add("__meta_hetzner_server_id", fmt.Sprintf("%d", server.ServerNumber))
|
|
|
|
m.Add("__meta_hetzner_server_name", server.ServerName)
|
|
|
|
m.Add("__meta_hetzner_datacenter", strings.ToLower(server.DC))
|
|
|
|
m.Add("__meta_hetzner_public_ipv4", server.ServerIP)
|
|
|
|
for _, subnet := range server.Subnet {
|
|
|
|
ip := net.ParseIP(subnet.IP)
|
|
|
|
if ip.To4() == nil {
|
|
|
|
m.Add("__meta_hetzner_public_ipv6_network", fmt.Sprintf("%s/%s", subnet.IP, subnet.Mask))
|
|
|
|
break
|
|
|
|
}
|
2024-01-15 09:13:22 +00:00
|
|
|
}
|
2024-01-20 14:52:41 +00:00
|
|
|
m.Add("__meta_hetzner_server_status", server.Status)
|
|
|
|
|
|
|
|
m.Add("__meta_hetzner_robot_product", server.Product)
|
|
|
|
m.Add("__meta_hetzner_robot_cancelled", fmt.Sprintf("%t", server.Canceled))
|
|
|
|
|
|
|
|
ms = append(ms, m)
|
|
|
|
return ms
|
2024-01-15 09:13:22 +00:00
|
|
|
}
|
|
|
|
|
2024-01-20 14:52:41 +00:00
|
|
|
func getRobotServers(cfg *apiConfig) ([]RobotServer, error) {
|
|
|
|
// See https://robot.hetzner.com/doc/webservice/en.html#server
|
|
|
|
data, err := cfg.client.GetAPIResponse("/server")
|
2024-01-15 09:13:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot query hetzner robot api for servers: %w", err)
|
|
|
|
}
|
2024-01-20 14:52:41 +00:00
|
|
|
servers, err := parseRobotServers(data)
|
2024-01-15 09:13:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return servers, nil
|
|
|
|
}
|
|
|
|
|
2024-01-20 14:52:41 +00:00
|
|
|
func parseRobotServers(data []byte) ([]RobotServer, error) {
|
|
|
|
var serverEntries []RobotServerEntry
|
|
|
|
err := json.Unmarshal(data, &serverEntries)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot unmarshal RobotServer list from %q: %w", data, err)
|
|
|
|
}
|
|
|
|
servers := make([]RobotServer, len(serverEntries))
|
|
|
|
for i := range serverEntries {
|
|
|
|
servers[i] = serverEntries[i].Server
|
2024-01-15 09:13:22 +00:00
|
|
|
}
|
2024-01-20 14:52:41 +00:00
|
|
|
return servers, nil
|
|
|
|
}
|
2024-01-15 09:13:22 +00:00
|
|
|
|
2024-01-20 14:52:41 +00:00
|
|
|
// RobotServerEntry represents a single server entry in hetzner robot server response.
|
|
|
|
//
|
|
|
|
// See https://robot.hetzner.com/doc/webservice/en.html#server
|
|
|
|
type RobotServerEntry struct {
|
|
|
|
Server RobotServer `json:"server"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// RobotServer represents the structure of hetzner robot server data.
|
|
|
|
//
|
|
|
|
// See https://robot.hetzner.com/doc/webservice/en.html#server
|
|
|
|
type RobotServer struct {
|
|
|
|
ServerIP string `json:"server_ip"`
|
|
|
|
ServerIPV6 string `json:"server_ipv6_net"`
|
|
|
|
ServerNumber int `json:"server_number"`
|
|
|
|
ServerName string `json:"server_name"`
|
|
|
|
DC string `json:"dc"`
|
|
|
|
Status string `json:"status"`
|
|
|
|
Product string `json:"product"`
|
|
|
|
Canceled bool `json:"cancelled"`
|
|
|
|
Subnet []RobotSubnet `json:"subnet"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// RobotSubnet represents the structure of hetzner robot subnet data.
|
|
|
|
//
|
|
|
|
// See https://robot.hetzner.com/doc/webservice/en.html#server
|
|
|
|
type RobotSubnet struct {
|
|
|
|
IP string `json:"ip"`
|
|
|
|
Mask string `json:"mask"`
|
2024-01-15 09:13:22 +00:00
|
|
|
}
|