mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-01 14:47:38 +00:00
3d55605ae5
This commit adds support for [PuppetDB](https://www.puppet.com/docs/puppetdb/8/overview.html) service discovery to the `vmagent` and `victoria-metrics-single` components. Related issue https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5744
151 lines
4.1 KiB
Go
151 lines
4.1 KiB
Go
package puppetdb
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
|
)
|
|
|
|
const (
|
|
separator = ","
|
|
)
|
|
|
|
type resource struct {
|
|
Certname string `json:"certname"`
|
|
Resource string `json:"resource"`
|
|
Type string `json:"type"`
|
|
Title string `json:"title"`
|
|
Exported bool `json:"exported"`
|
|
Tags []string `json:"tags"`
|
|
File string `json:"file"`
|
|
Environment string `json:"environment"`
|
|
Parameters parameters `json:"parameters"`
|
|
}
|
|
|
|
type parameters map[string]interface{}
|
|
|
|
// addToLabels add Parameters map to existing labels.
|
|
// See: https://github.com/prometheus/prometheus/blob/685493187ec5f5734777769f595cf8418d49900d/discovery/puppetdb/resources.go#L39
|
|
func (p *parameters) addToLabels(keyPrefix string, m *promutils.Labels) {
|
|
if p == nil {
|
|
return
|
|
}
|
|
|
|
for k, v := range *p {
|
|
var labelValue string
|
|
switch value := v.(type) {
|
|
case string:
|
|
labelValue = value
|
|
case bool:
|
|
labelValue = strconv.FormatBool(value)
|
|
case int64:
|
|
labelValue = strconv.FormatInt(value, 10)
|
|
case float64:
|
|
labelValue = strconv.FormatFloat(value, 'g', -1, 64)
|
|
case []string:
|
|
labelValue = separator + strings.Join(value, separator) + separator
|
|
case []interface{}:
|
|
if len(value) == 0 {
|
|
continue
|
|
}
|
|
values := make([]string, len(value))
|
|
for i, v := range value {
|
|
switch value := v.(type) {
|
|
case string:
|
|
values[i] = value
|
|
case bool:
|
|
values[i] = strconv.FormatBool(value)
|
|
case int64:
|
|
values[i] = strconv.FormatInt(value, 10)
|
|
case float64:
|
|
values[i] = strconv.FormatFloat(value, 'g', -1, 64)
|
|
case []string:
|
|
values[i] = separator + strings.Join(value, separator) + separator
|
|
}
|
|
}
|
|
labelValue = strings.Join(values, separator)
|
|
case map[string]interface{}:
|
|
subParameter := parameters(value)
|
|
subParameter.addToLabels(keyPrefix+discoveryutils.SanitizeLabelName(k+"_"), m)
|
|
default:
|
|
continue
|
|
}
|
|
if labelValue == "" {
|
|
continue
|
|
}
|
|
name := discoveryutils.SanitizeLabelName(k)
|
|
m.Add(keyPrefix+name, labelValue)
|
|
}
|
|
}
|
|
|
|
func getResourceList(cfg *apiConfig) ([]resource, error) {
|
|
body := struct {
|
|
Query string `json:"query"`
|
|
}{cfg.query}
|
|
|
|
bodyBytes, err := json.Marshal(body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
modifyRequestFunc := func(request *http.Request) {
|
|
request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
|
request.Header.Set("Accept", "application/json")
|
|
request.Header.Set("Content-Type", "application/json")
|
|
request.Method = http.MethodPost
|
|
}
|
|
|
|
// https://www.puppet.com/docs/puppetdb/8/api/query/v4/overview#pdbqueryv4
|
|
resp, err := cfg.client.GetAPIResponseWithReqParams("/pdb/query/v4", modifyRequestFunc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var resources []resource
|
|
if err = json.Unmarshal(resp, &resources); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return resources, nil
|
|
}
|
|
|
|
func getResourceLabels(resources []resource, cfg *apiConfig) []*promutils.Labels {
|
|
ms := make([]*promutils.Labels, 0, len(resources))
|
|
|
|
for _, res := range resources {
|
|
m := promutils.NewLabels(18)
|
|
|
|
m.Add("__address__", discoveryutils.JoinHostPort(res.Certname, cfg.port))
|
|
m.Add("__meta_puppetdb_certname", res.Certname)
|
|
m.Add("__meta_puppetdb_environment", res.Environment)
|
|
m.Add("__meta_puppetdb_exported", fmt.Sprintf("%t", res.Exported))
|
|
m.Add("__meta_puppetdb_file", res.File)
|
|
m.Add("__meta_puppetdb_query", cfg.query)
|
|
m.Add("__meta_puppetdb_resource", res.Resource)
|
|
m.Add("__meta_puppetdb_title", res.Title)
|
|
m.Add("__meta_puppetdb_type", res.Type)
|
|
|
|
if len(res.Tags) > 0 {
|
|
//discoveryutils.AddTagsToLabels(m, resource.Tags, "__meta_puppetdb_tags", separator)
|
|
m.Add("__meta_puppetdb_tags", separator+strings.Join(res.Tags, separator)+separator)
|
|
}
|
|
|
|
// Parameters are not included by default. This should only be enabled
|
|
// on select resources as it might expose secrets on the Prometheus UI
|
|
// for certain resources.
|
|
if cfg.includeParameters {
|
|
res.Parameters.addToLabels("__meta_puppetdb_parameter_", m)
|
|
}
|
|
|
|
ms = append(ms, m)
|
|
}
|
|
|
|
return ms
|
|
}
|