diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 18e6bc18fb..d83f267e5b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -15,6 +15,8 @@ The following tip changes can be tested by building VictoriaMetrics components f ## tip +* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): [dockerswarm_sd_configs](https://docs.victoriametrics.com/sd_configs.html#dockerswarm_sd_configs): apply `filters` only to objects of the specified `role`. Previously filters were applied to all the objects, which could cause errors when different types of objects were used with filters that were not compatible with them. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3579). + ## [v1.86.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.86.1) diff --git a/lib/promscrape/discovery/dockerswarm/api.go b/lib/promscrape/discovery/dockerswarm/api.go index 35d2ab9742..ef33775ba1 100644 --- a/lib/promscrape/discovery/dockerswarm/api.go +++ b/lib/promscrape/discovery/dockerswarm/api.go @@ -16,6 +16,9 @@ type apiConfig struct { client *discoveryutils.Client port int + // role is the type of objects to discover. + role string + // filtersQueryArg contains escaped `filters` query arg to add to each request to Docker Swarm API. filtersQueryArg string } @@ -49,11 +52,12 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) { 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 string) ([]byte, error) { - if len(cfg.filtersQueryArg) > 0 { +func (cfg *apiConfig) getAPIResponse(path, filtersQueryArg string) ([]byte, error) { + if len(filtersQueryArg) > 0 { separator := "?" if strings.Contains(path, "?") { separator = "&" diff --git a/lib/promscrape/discovery/dockerswarm/dockerswarm.go b/lib/promscrape/discovery/dockerswarm/dockerswarm.go index bfe7a06971..a36b5163ab 100644 --- a/lib/promscrape/discovery/dockerswarm/dockerswarm.go +++ b/lib/promscrape/discovery/dockerswarm/dockerswarm.go @@ -15,6 +15,12 @@ var SDCheckInterval = flag.Duration("promscrape.dockerswarmSDCheckInterval", 30* "This works only if dockerswarm_sd_configs is configured in '-promscrape.config' file. "+ "See https://docs.victoriametrics.com/sd_configs.html#dockerswarm_sd_configs for details") +const ( + roleTasks = "tasks" + roleServices = "services" + roleNodes = "nodes" +) + // SDConfig represents docker swarm service discovery configuration // // See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dockerswarm_sd_config @@ -43,11 +49,11 @@ func (sdc *SDConfig) GetLabels(baseDir string) ([]*promutils.Labels, error) { return nil, fmt.Errorf("cannot get API config: %w", err) } switch sdc.Role { - case "tasks": + case roleTasks: return getTasksLabels(cfg) - case "services": + case roleServices: return getServicesLabels(cfg) - case "nodes": + case roleNodes: return getNodesLabels(cfg) default: return nil, fmt.Errorf("unexpected `role`: %q; must be one of `tasks`, `services` or `nodes`; skipping it", sdc.Role) diff --git a/lib/promscrape/discovery/dockerswarm/network.go b/lib/promscrape/discovery/dockerswarm/network.go index fabfbf1497..f830254f6b 100644 --- a/lib/promscrape/discovery/dockerswarm/network.go +++ b/lib/promscrape/discovery/dockerswarm/network.go @@ -28,7 +28,7 @@ func getNetworksLabelsByNetworkID(cfg *apiConfig) (map[string]*promutils.Labels, } func getNetworks(cfg *apiConfig) ([]network, error) { - resp, err := cfg.getAPIResponse("/networks") + resp, err := cfg.getAPIResponse("/networks", "") if err != nil { return nil, fmt.Errorf("cannot query dockerswarm api for networks: %w", err) } diff --git a/lib/promscrape/discovery/dockerswarm/nodes.go b/lib/promscrape/discovery/dockerswarm/nodes.go index 1800e40973..daafd71c78 100644 --- a/lib/promscrape/discovery/dockerswarm/nodes.go +++ b/lib/promscrape/discovery/dockerswarm/nodes.go @@ -47,7 +47,12 @@ func getNodesLabels(cfg *apiConfig) ([]*promutils.Labels, error) { } func getNodes(cfg *apiConfig) ([]node, error) { - resp, err := cfg.getAPIResponse("/nodes") + filtersQueryArg := "" + if cfg.role == roleNodes { + filtersQueryArg = cfg.filtersQueryArg + } + + resp, err := cfg.getAPIResponse("/nodes", filtersQueryArg) if err != nil { return nil, fmt.Errorf("cannot query dockerswarm api for nodes: %w", err) } diff --git a/lib/promscrape/discovery/dockerswarm/services.go b/lib/promscrape/discovery/dockerswarm/services.go index 431665228f..7b09d43650 100644 --- a/lib/promscrape/discovery/dockerswarm/services.go +++ b/lib/promscrape/discovery/dockerswarm/services.go @@ -59,7 +59,12 @@ func getServicesLabels(cfg *apiConfig) ([]*promutils.Labels, error) { } func getServices(cfg *apiConfig) ([]service, error) { - data, err := cfg.getAPIResponse("/services") + filtersQueryArg := "" + if cfg.role == roleServices { + filtersQueryArg = cfg.filtersQueryArg + } + + data, err := cfg.getAPIResponse("/services", filtersQueryArg) if err != nil { return nil, fmt.Errorf("cannot query dockerswarm api for services: %w", err) } diff --git a/lib/promscrape/discovery/dockerswarm/tasks.go b/lib/promscrape/discovery/dockerswarm/tasks.go index 21aafb2e6c..f0e0d94388 100644 --- a/lib/promscrape/discovery/dockerswarm/tasks.go +++ b/lib/promscrape/discovery/dockerswarm/tasks.go @@ -62,7 +62,12 @@ func getTasksLabels(cfg *apiConfig) ([]*promutils.Labels, error) { } func getTasks(cfg *apiConfig) ([]task, error) { - resp, err := cfg.getAPIResponse("/tasks") + filtersQueryArg := "" + if cfg.role == roleTasks { + filtersQueryArg = cfg.filtersQueryArg + } + + resp, err := cfg.getAPIResponse("/tasks", filtersQueryArg) if err != nil { return nil, fmt.Errorf("cannot query dockerswarm api for tasks: %w", err) }