mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-29 23:30:04 +01:00
b4ad3a3b4c
- Add a comment describing the purpose of the `role` field inside `apiConfig` struct - Revert changes at lib/promscrape/discovery/dockerswarm/dockerswarm.go , since they reduce code readability. E.g. the reader needs to look up the named string constants in order to get their values.
89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
package dockerswarm
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
|
)
|
|
|
|
var configMap = discoveryutils.NewConfigMap()
|
|
|
|
type apiConfig struct {
|
|
client *discoveryutils.Client
|
|
port int
|
|
|
|
// role is the type of objects to discover.
|
|
//
|
|
// filtersQueryArg is applied only to the given role - the rest of objects are queried without filters.
|
|
role string
|
|
|
|
// filtersQueryArg contains escaped `filters` query arg to add to each request to Docker Swarm API.
|
|
filtersQueryArg string
|
|
}
|
|
|
|
func getAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
|
|
v, err := configMap.Get(sdc, func() (interface{}, error) { return newAPIConfig(sdc, baseDir) })
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return v.(*apiConfig), nil
|
|
}
|
|
|
|
func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
|
|
cfg := &apiConfig{
|
|
port: sdc.Port,
|
|
filtersQueryArg: getFiltersQueryArg(sdc.Filters),
|
|
}
|
|
if cfg.port == 0 {
|
|
cfg.port = 80
|
|
}
|
|
ac, err := sdc.HTTPClientConfig.NewConfig(baseDir)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot parse auth config: %w", err)
|
|
}
|
|
proxyAC, err := sdc.ProxyClientConfig.NewConfig(baseDir)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
|
|
}
|
|
client, err := discoveryutils.NewClient(sdc.Host, ac, sdc.ProxyURL, proxyAC)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot create HTTP client for %q: %w", sdc.Host, err)
|
|
}
|
|
cfg.client = client
|
|
cfg.role = sdc.Role
|
|
return cfg, nil
|
|
}
|
|
|
|
func (cfg *apiConfig) getAPIResponse(path, filtersQueryArg string) ([]byte, error) {
|
|
if len(filtersQueryArg) > 0 {
|
|
separator := "?"
|
|
if strings.Contains(path, "?") {
|
|
separator = "&"
|
|
}
|
|
path += separator + "filters=" + cfg.filtersQueryArg
|
|
}
|
|
return cfg.client.GetAPIResponse(path)
|
|
}
|
|
|
|
// Encodes filters as `map[string][]string` and then marshals it to JSON.
|
|
// Reference: https://docs.docker.com/engine/api/v1.41/#tag/Task
|
|
func getFiltersQueryArg(filters []Filter) string {
|
|
if len(filters) == 0 {
|
|
return ""
|
|
}
|
|
|
|
m := make(map[string][]string)
|
|
for _, f := range filters {
|
|
m[f.Name] = f.Values
|
|
}
|
|
buf, err := json.Marshal(m)
|
|
if err != nil {
|
|
logger.Panicf("BUG: unexpected error in json.Marshal: %s", err)
|
|
}
|
|
return url.QueryEscape(string(buf))
|
|
}
|