Repository: VictoriaMetrics/VictoriaMetrics
Pull request #4346 (2023-05-25 19:26:50)

update docs-sync Makefile command, add hugo front-matter

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/VictoriaMetrics/VictoriaMetrics/pull/4346?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VictoriaMetrics) Report
Patch coverage has no change and project coverage change: **`+0.03`** :tada:
> Comparison is base [(`76f7e66`)](https://app.codecov.io/gh/VictoriaMetrics/VictoriaMetrics/commit/76f7e66d8e7d0bb05b3577466227651ce8d779ff?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VictoriaMetrics) 61.20% compared to head [(`864d0de`)](https://app.codecov.io/gh/VictoriaMetrics/VictoriaMetrics/pull/4346?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VictoriaMetrics) 61.24%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4346      +/-   ##
==========================================
+ Coverage   61.20%   61.24%   +0.03%     
==========================================
  Files         330      330              
  Lines       58997    58998       +1     
==========================================
+ Hits        36112    36135      +23     
+ Misses      20914    20899      -15     
+ Partials     1971     1964       -7     
```


[see 5 files with indirect coverage changes](https://app.codecov.io/gh/VictoriaMetrics/VictoriaMetrics/pull/4346/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VictoriaMetrics)


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/VictoriaMetrics/VictoriaMetrics/pull/4346?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VictoriaMetrics).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=VictoriaMetrics).


Patch:
diff --git a/Makefile b/Makefile
index cddd06ced..551c587c7 100644
--- a/Makefile
+++ b/Makefile
@@ -418,27 +418,37 @@ check-licenses: install-wwhrd
 	wwhrd check -f .wwhrd.yml
 
 copy-docs:
-	echo '' > ${DST}
+	echo "---" > ${DST}
 	@if [ ${ORDER} -ne 0 ]; then \
-		echo "---\nsort: ${ORDER}\n---\n" > ${DST}; \
+		echo "sort: ${ORDER}" >> ${DST}; \
+		echo "weight: ${ORDER}" >> ${DST}; \
+		echo "menu:\n  docs:\n    parent: 'victoriametrics'\n    weight: ${ORDER}" >> ${DST}; \
 	fi
+
+	echo "title: ${TITLE}" >> ${DST}
+	@if [ ${OLD_URL} ]; then \
+		echo "aliases:\n  - ${OLD_URL}" >> ${DST}; \
+	fi
+	echo "---" >> ${DST}
 	cat ${SRC} >> ${DST}
 	sed -i='.tmp' 's/<img src=\"docs\//<img src=\"/' ${DST}
 	rm -rf docs/*.tmp
 
-# Copies docs for all components and adds the order tag.
-# For ORDER=0 it adds no order tag.
+# Copies docs for all components and adds the order/weight tag, title, menu position and alias with the backward compatible link for the old site.
+# For ORDER=0 it adds no order tag/weight tag.
+# FOR OLD_URL - relative link, used for backward compatibility with the link from documentation based on GitHub pages (old one)
+# FOR OLD_URL='' it adds no alias, it should be empty for every new page, don't change it for already existing links. 
 # Images starting with <img src="docs/ are replaced with <img src="
-# Cluster docs are supposed to be ordered as 9th.
+# Cluster docs are supposed to be ordered as 2nd.
 # The rest of docs is ordered manually.
 docs-sync:
-	SRC=README.md DST=docs/README.md ORDER=0 $(MAKE) copy-docs
-	SRC=README.md DST=docs/Single-server-VictoriaMetrics.md ORDER=1 $(MAKE) copy-docs
-	SRC=app/vmagent/README.md DST=docs/vmagent.md ORDER=3 $(MAKE) copy-docs
-	SRC=app/vmalert/README.md DST=docs/vmalert.md ORDER=4 $(MAKE) copy-docs
-	SRC=app/vmauth/README.md DST=docs/vmauth.md ORDER=5 $(MAKE) copy-docs
-	SRC=app/vmbackup/README.md DST=docs/vmbackup.md ORDER=6 $(MAKE) copy-docs
-	SRC=app/vmrestore/README.md DST=docs/vmrestore.md ORDER=7 $(MAKE) copy-docs
-	SRC=app/vmctl/README.md DST=docs/vmctl.md ORDER=8 $(MAKE) copy-docs
-	SRC=app/vmgateway/README.md DST=docs/vmgateway.md ORDER=9 $(MAKE) copy-docs
-	SRC=app/vmbackupmanager/README.md DST=docs/vmbackupmanager.md ORDER=10 $(MAKE) copy-docs
+	SRC=README.md DST=docs/README.md OLD_URL='' ORDER=0 TITLE=VictoriaMetrics $(MAKE) copy-docs
+	SRC=README.md DST=docs/Single-server-VictoriaMetrics.md OLD_URL='/Single-server-VictoriaMetrics.html' TITLE=VictoriaMetrics ORDER=1 $(MAKE) copy-docs
+	SRC=app/vmagent/README.md DST=docs/vmagent.md OLD_URL='/vmagent.html' ORDER=3 TITLE=vmagent $(MAKE) copy-docs
+	SRC=app/vmalert/README.md DST=docs/vmalert.md OLD_URL='/vmalert.html' ORDER=4 TITLE=vmalert $(MAKE) copy-docs
+	SRC=app/vmauth/README.md DST=docs/vmauth.md OLD_URL='/vmauth.html' ORDER=5 TITLE=vmauth $(MAKE) copy-docs
+	SRC=app/vmbackup/README.md DST=docs/vmbackup.md OLD_URL='/vmbackup.html' ORDER=6 TITLE=vmbackup $(MAKE) copy-docs
+	SRC=app/vmrestore/README.md DST=docs/vmrestore.md OLD_URL='/vmrestore.html' ORDER=7 TITLE=vmrestore $(MAKE) copy-docs
+	SRC=app/vmctl/README.md DST=docs/vmctl.md OLD_URL='/vmctl.html' ORDER=8 TITLE=vmctl $(MAKE) copy-docs
+	SRC=app/vmgateway/README.md DST=docs/vmgateway.md OLD_URL='/vmgateway.html' ORDER=9 TITLE=vmgateway $(MAKE) copy-docs
+	SRC=app/vmbackupmanager/README.md DST=docs/vmbackupmanager.md OLD_URL='/vmbackupmanager.html' ORDER=10 TITLE=vmbackupmanager $(MAKE) copy-docs
diff --git a/docs/README.md b/docs/README.md
index 4da2431b6..fa75034ed 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,4 +1,6 @@
-
+---
+title: VictoriaMetrics
+---
 # VictoriaMetrics
 
 [![Latest Release](https://img.shields.io/github/release/VictoriaMetrics/VictoriaMetrics.svg?style=flat-square)](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest)
diff --git a/docs/Single-server-VictoriaMetrics.md b/docs/Single-server-VictoriaMetrics.md
index 6bd0f45c0..b082b886d 100644
--- a/docs/Single-server-VictoriaMetrics.md
+++ b/docs/Single-server-VictoriaMetrics.md
@@ -1,7 +1,14 @@
 ---
 sort: 1
+weight: 1
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 1
+title: VictoriaMetrics
+aliases:
+  - /Single-server-VictoriaMetrics.html
 ---
-
 # VictoriaMetrics
 
 [![Latest Release](https://img.shields.io/github/release/VictoriaMetrics/VictoriaMetrics.svg?style=flat-square)](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest)
diff --git a/docs/vmagent.md b/docs/vmagent.md
index 4dec48853..4209bf4c2 100644
--- a/docs/vmagent.md
+++ b/docs/vmagent.md
@@ -1,7 +1,14 @@
 ---
 sort: 3
+weight: 3
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 3
+title: vmagent
+aliases:
+  - /vmagent.html
 ---
-
 # vmagent
 
 `vmagent` is a tiny agent which helps you collect metrics from various sources,
diff --git a/docs/vmalert.md b/docs/vmalert.md
index 27c77f4b7..c560d28b7 100644
--- a/docs/vmalert.md
+++ b/docs/vmalert.md
@@ -1,7 +1,14 @@
 ---
 sort: 4
+weight: 4
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 4
+title: vmalert
+aliases:
+  - /vmalert.html
 ---
-
 # vmalert
 
 `vmalert` executes a list of the given [alerting](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/)
diff --git a/docs/vmauth.md b/docs/vmauth.md
index 2840ea7a7..e5a564455 100644
--- a/docs/vmauth.md
+++ b/docs/vmauth.md
@@ -1,7 +1,14 @@
 ---
 sort: 5
+weight: 5
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 5
+title: vmauth
+aliases:
+  - /vmauth.html
 ---
-
 # vmauth
 
 `vmauth` is a simple auth proxy, router and [load balancer](#load-balancing) for [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics).
diff --git a/docs/vmbackup.md b/docs/vmbackup.md
index 407912bec..bbbaabd37 100644
--- a/docs/vmbackup.md
+++ b/docs/vmbackup.md
@@ -1,7 +1,14 @@
 ---
 sort: 6
+weight: 6
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 6
+title: vmbackup
+aliases:
+  - /vmbackup.html
 ---
-
 # vmbackup
 
 `vmbackup` creates VictoriaMetrics data backups from [instant snapshots](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#how-to-work-with-snapshots).
diff --git a/docs/vmbackupmanager.md b/docs/vmbackupmanager.md
index 1aace3154..e8c143be9 100644
--- a/docs/vmbackupmanager.md
+++ b/docs/vmbackupmanager.md
@@ -1,7 +1,14 @@
 ---
 sort: 10
+weight: 10
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 10
+title: vmbackupmanager
+aliases:
+  - /vmbackupmanager.html
 ---
-
 ## vmbackupmanager
 
 ***vmbackupmanager is a part of [enterprise package](https://docs.victoriametrics.com/enterprise.html). It is available for download and evaluation at [releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases)***
diff --git a/docs/vmctl.md b/docs/vmctl.md
index f93057ae1..c01e22bfe 100644
--- a/docs/vmctl.md
+++ b/docs/vmctl.md
@@ -1,7 +1,14 @@
 ---
 sort: 8
+weight: 8
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 8
+title: vmctl
+aliases:
+  - /vmctl.html
 ---
-
 # vmctl
 
 VictoriaMetrics command-line tool
diff --git a/docs/vmgateway.md b/docs/vmgateway.md
index 0a13004ab..b3a053539 100644
--- a/docs/vmgateway.md
+++ b/docs/vmgateway.md
@@ -1,7 +1,14 @@
 ---
 sort: 9
+weight: 9
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 9
+title: vmgateway
+aliases:
+  - /vmgateway.html
 ---
-
 # vmgateway
 
 ***vmgateway is a part of [enterprise package](https://docs.victoriametrics.com/enterprise.html). It is available for download and evaluation at [releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases)***
diff --git a/docs/vmrestore.md b/docs/vmrestore.md
index 57223826e..613e9585a 100644
--- a/docs/vmrestore.md
+++ b/docs/vmrestore.md
@@ -1,7 +1,14 @@
 ---
 sort: 7
+weight: 7
+menu:
+  docs:
+    parent: 'victoriametrics'
+    weight: 7
+title: vmrestore
+aliases:
+  - /vmrestore.html
 ---
-
 # vmrestore
 
 `vmrestore` restores data from backups created by [vmbackup](https://docs.victoriametrics.com/vmbackup.html).
diff --git a/lib/promauth/config.go b/lib/promauth/config.go
index 3da9a6697..4c66ec359 100644
--- a/lib/promauth/config.go
+++ b/lib/promauth/config.go
@@ -123,6 +123,9 @@ type HTTPClientConfig struct {
 
 	// Headers contains optional HTTP headers, which must be sent in the request to the server
 	Headers []string `yaml:"headers,omitempty"`
+
+	// FollowRedirects specifies whether the client should follow HTTP 3xx redirects.
+	FollowRedirects *bool `yaml:"follow_redirects,omitempty"`
 }
 
 // ProxyClientConfig represents proxy client config.
diff --git a/lib/promscrape/config.go b/lib/promscrape/config.go
index e5c07eff1..cc1b9529a 100644
--- a/lib/promscrape/config.go
+++ b/lib/promscrape/config.go
@@ -245,7 +245,6 @@ type ScrapeConfig struct {
 	MetricsPath          string                      `yaml:"metrics_path,omitempty"`
 	HonorLabels          bool                        `yaml:"honor_labels,omitempty"`
 	HonorTimestamps      *bool                       `yaml:"honor_timestamps,omitempty"`
-	FollowRedirects      *bool                       `yaml:"follow_redirects,omitempty"`
 	Scheme               string                      `yaml:"scheme,omitempty"`
 	Params               map[string][]string         `yaml:"params,omitempty"`
 	HTTPClientConfig     promauth.HTTPClientConfig   `yaml:",inline"`
@@ -990,8 +989,8 @@ func getScrapeWorkConfig(sc *ScrapeConfig, baseDir string, globalCfg *GlobalConf
 		honorTimestamps = *sc.HonorTimestamps
 	}
 	denyRedirects := false
-	if sc.FollowRedirects != nil {
-		denyRedirects = !*sc.FollowRedirects
+	if sc.HTTPClientConfig.FollowRedirects != nil {
+		denyRedirects = !*sc.HTTPClientConfig.FollowRedirects
 	}
 	metricsPath := sc.MetricsPath
 	if metricsPath == "" {
diff --git a/lib/promscrape/discovery/azure/api.go b/lib/promscrape/discovery/azure/api.go
index 2ff084193..bd580cec0 100644
--- a/lib/promscrape/discovery/azure/api.go
+++ b/lib/promscrape/discovery/azure/api.go
@@ -110,7 +110,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, err
 	}
-	c, err := discoveryutils.NewClient(env.ResourceManagerEndpoint, ac, sdc.ProxyURL, proxyAC)
+	c, err := discoveryutils.NewClient(env.ResourceManagerEndpoint, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create client for %q: %w", env.ResourceManagerEndpoint, err)
 	}
@@ -230,7 +230,7 @@ func getRefreshTokenFunc(sdc *SDConfig, ac, proxyAC *promauth.Config, env *cloud
 		return nil, fmt.Errorf("unsupported `authentication_method: %q` only `OAuth` and `ManagedIdentity` are supported", authenticationMethod)
 	}
 
-	authClient, err := discoveryutils.NewClient(tokenEndpoint, ac, sdc.ProxyURL, proxyAC)
+	authClient, err := discoveryutils.NewClient(tokenEndpoint, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot build auth client: %w", err)
 	}
diff --git a/lib/promscrape/discovery/consul/api.go b/lib/promscrape/discovery/consul/api.go
index 8ba3b5204..dabd10ead 100644
--- a/lib/promscrape/discovery/consul/api.go
+++ b/lib/promscrape/discovery/consul/api.go
@@ -80,7 +80,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", apiServer, err)
 	}
diff --git a/lib/promscrape/discovery/consulagent/api.go b/lib/promscrape/discovery/consulagent/api.go
index 8dc706f36..9d5c4761e 100644
--- a/lib/promscrape/discovery/consulagent/api.go
+++ b/lib/promscrape/discovery/consulagent/api.go
@@ -74,7 +74,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", apiServer, err)
 	}
diff --git a/lib/promscrape/discovery/digitalocean/api.go b/lib/promscrape/discovery/digitalocean/api.go
index b42cc9840..7d4cad4bb 100644
--- a/lib/promscrape/discovery/digitalocean/api.go
+++ b/lib/promscrape/discovery/digitalocean/api.go
@@ -36,7 +36,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", apiServer, err)
 	}
@@ -56,7 +56,6 @@ func getAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 		return nil, err
 	}
 	return v.(*apiConfig), nil
-
 }
 
 const dropletsAPIPath = "/v2/droplets"
diff --git a/lib/promscrape/discovery/docker/api.go b/lib/promscrape/discovery/docker/api.go
index e09d063ab..8301c3fd5 100644
--- a/lib/promscrape/discovery/docker/api.go
+++ b/lib/promscrape/discovery/docker/api.go
@@ -50,7 +50,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(sdc.Host, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(sdc.Host, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", sdc.Host, err)
 	}
diff --git a/lib/promscrape/discovery/dockerswarm/api.go b/lib/promscrape/discovery/dockerswarm/api.go
index ebd8e07ed..160e00d3d 100644
--- a/lib/promscrape/discovery/dockerswarm/api.go
+++ b/lib/promscrape/discovery/dockerswarm/api.go
@@ -49,7 +49,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(sdc.Host, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(sdc.Host, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", sdc.Host, err)
 	}
diff --git a/lib/promscrape/discovery/eureka/api.go b/lib/promscrape/discovery/eureka/api.go
index 93e5e2eeb..03670870a 100644
--- a/lib/promscrape/discovery/eureka/api.go
+++ b/lib/promscrape/discovery/eureka/api.go
@@ -34,7 +34,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", apiServer, err)
 	}
@@ -50,7 +50,6 @@ func getAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 		return nil, err
 	}
 	return v.(*apiConfig), nil
-
 }
 
 func getAPIResponse(cfg *apiConfig, path string) ([]byte, error) {
diff --git a/lib/promscrape/discovery/http/api.go b/lib/promscrape/discovery/http/api.go
index d8ed5adbf..107167faf 100644
--- a/lib/promscrape/discovery/http/api.go
+++ b/lib/promscrape/discovery/http/api.go
@@ -44,7 +44,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", apiServer, err)
 	}
diff --git a/lib/promscrape/discovery/kuma/api.go b/lib/promscrape/discovery/kuma/api.go
index f0a9f8096..c160d15e6 100644
--- a/lib/promscrape/discovery/kuma/api.go
+++ b/lib/promscrape/discovery/kuma/api.go
@@ -60,7 +60,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", apiServer, err)
 	}
diff --git a/lib/promscrape/discovery/nomad/api.go b/lib/promscrape/discovery/nomad/api.go
index 577bca36e..33aefa295 100644
--- a/lib/promscrape/discovery/nomad/api.go
+++ b/lib/promscrape/discovery/nomad/api.go
@@ -68,7 +68,7 @@ func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
 	}
-	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC)
+	client, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, sdc.HTTPClientConfig.FollowRedirects)
 	if err != nil {
 		return nil, fmt.Errorf("cannot create HTTP client for %q: %w", apiServer, err)
 	}
diff --git a/lib/promscrape/discoveryutils/client.go b/lib/promscrape/discoveryutils/client.go
index f6dfdcf83..e9d1bde1f 100644
--- a/lib/promscrape/discoveryutils/client.go
+++ b/lib/promscrape/discoveryutils/client.go
@@ -83,7 +83,7 @@ type HTTPClient struct {
 var defaultDialer = &net.Dialer{}
 
 // NewClient returns new Client for the given args.
-func NewClient(apiServer string, ac *promauth.Config, proxyURL *proxy.URL, proxyAC *promauth.Config) (*Client, error) {
+func NewClient(apiServer string, ac *promauth.Config, proxyURL *proxy.URL, proxyAC *promauth.Config, followRedirects *bool) (*Client, error) {
 	u, err := url.Parse(apiServer)
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse apiServer=%q: %w", apiServer, err)
@@ -139,6 +139,14 @@ func NewClient(apiServer string, ac *promauth.Config, proxyURL *proxy.URL, proxy
 			ac.SetHeaders(req, true)
 		}
 	}
+	if followRedirects != nil && !*followRedirects {
+		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+			return http.ErrUseLastResponse
+		}
+		blockingClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+			return http.ErrUseLastResponse
+		}
+	}
 	setHTTPProxyHeaders := func(req *http.Request) {}
 	if proxyAC != nil {
 		setHTTPProxyHeaders = func(req *http.Request) {
@@ -186,7 +194,8 @@ func (c *Client) GetAPIResponse(path string) ([]byte, error) {
 }
 
 func (c *Client) getAPIResponseWithConcurrencyLimit(ctx context.Context, client *HTTPClient, path string,
-	modifyRequest RequestCallback, inspectResponse ResponseCallback) ([]byte, error) {
+	modifyRequest RequestCallback, inspectResponse ResponseCallback,
+) ([]byte, error) {
 	// Limit the number of concurrent API requests.
 	concurrencyLimitChOnce.Do(concurrencyLimitChInit)
 	t := timerpool.Get(*maxWaitTime)


Test patch:
diff --git a/app/vmselect/graphite/eval_test.go b/app/vmselect/graphite/eval_test.go
index 053c92a4f..4570d8338 100644
--- a/app/vmselect/graphite/eval_test.go
+++ b/app/vmselect/graphite/eval_test.go
@@ -3977,6 +3977,7 @@ func compareSeries(ss, ssExpected []*series, expr graphiteql.Expr) error {
 		if !reflect.DeepEqual(s.Timestamps, sExpected.Timestamps) {
 			return fmt.Errorf("unexpected timestamps for series %q\ngot\n%d\nwant\n%d", s.Name, s.Timestamps, sExpected.Timestamps)
 		}
+
 		if !equalFloats(s.Values, sExpected.Values) {
 			return fmt.Errorf("unexpected values for series %q\ngot\n%g\nwant\n%g", s.Name, s.Values, sExpected.Values)
 		}
@@ -4009,7 +4010,7 @@ func equalFloats(a, b []float64) bool {
 		} else if math.IsNaN(v2) {
 			return false
 		}
-		eps := math.Abs(v1) / 1e15
+		eps := math.Abs(v1) / 1e9
 		if math.Abs(v1-v2) > eps {
 			return false
 		}
diff --git a/lib/promscrape/discovery/azure/machine_test.go b/lib/promscrape/discovery/azure/machine_test.go
index f2ba253ca..90141999e 100644
--- a/lib/promscrape/discovery/azure/machine_test.go
+++ b/lib/promscrape/discovery/azure/machine_test.go
@@ -66,7 +66,7 @@ func TestGetVirtualMachinesSuccess(t *testing.T) {
 				}
 			}))
 			defer testServer.Close()
-			c, err := discoveryutils.NewClient(testServer.URL, nil, nil, nil)
+			c, err := discoveryutils.NewClient(testServer.URL, nil, nil, nil, nil)
 			if err != nil {
 				t.Fatalf("unexpected error at client create: %s", err)
 			}
diff --git a/lib/promscrape/testdata/prometheus.yml b/lib/promscrape/testdata/prometheus.yml
index f185bfe6b..ecae9e7a3 100644
--- a/lib/promscrape/testdata/prometheus.yml
+++ b/lib/promscrape/testdata/prometheus.yml
@@ -1,5 +1,29 @@
 scrape_configs:
-- job_name: foo
-  file_sd_configs:
-  - files: ["file_sd_*.yml"]
-  - files: ["file_sd.json"]
+  - job_name: foo
+    scrape_interval: 54s
+    scrape_timeout: 12s
+    metrics_path: /foo/bar
+    scheme: https
+    honor_labels: true
+    honor_timestamps: false
+    follow_redirects: false
+    static_configs:
+      - targets: ["foo.bar", "aaa"]
+        labels:
+          x: y
+          __scrape_timeout__: "5s"
+  - job_name: file-job
+    file_sd_configs:
+      - files: ["file_sd_*.yml"]
+      - files: ["file_sd.json"]
+  - job_name: service-kubernetes
+    kubernetes_sd_configs:
+      - role: endpoints
+        api_server: "https://localhost:1234"
+        follow_redirects: true
+        tls_config:
+          cert_file: valid_cert_file
+          key_file: valid_key_file
+        basic_auth:
+          username: "myusername"
+          password: "mysecret"