mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-10 15:14:09 +00:00
app/vmauth: allow specifying an empty retry_status_codes and and zero drop_src_path_prefix_parts in order to override user-level setting
Previously `retry_status_codes: []` and `drop_src_path_prefix_parts: 0` at `url_map` were equivalent to missing values. This was resulting in using the user-level values instead.
This commit is contained in:
parent
51acf0179c
commit
4ee42e9e73
5 changed files with 41 additions and 25 deletions
|
@ -56,7 +56,7 @@ type UserInfo struct {
|
||||||
DefaultURL *URLPrefix `yaml:"default_url,omitempty"`
|
DefaultURL *URLPrefix `yaml:"default_url,omitempty"`
|
||||||
RetryStatusCodes []int `yaml:"retry_status_codes,omitempty"`
|
RetryStatusCodes []int `yaml:"retry_status_codes,omitempty"`
|
||||||
LoadBalancingPolicy string `yaml:"load_balancing_policy,omitempty"`
|
LoadBalancingPolicy string `yaml:"load_balancing_policy,omitempty"`
|
||||||
DropSrcPathPrefixParts int `yaml:"drop_src_path_prefix_parts,omitempty"`
|
DropSrcPathPrefixParts *int `yaml:"drop_src_path_prefix_parts,omitempty"`
|
||||||
TLSInsecureSkipVerify *bool `yaml:"tls_insecure_skip_verify,omitempty"`
|
TLSInsecureSkipVerify *bool `yaml:"tls_insecure_skip_verify,omitempty"`
|
||||||
TLSCAFile string `yaml:"tls_ca_file,omitempty"`
|
TLSCAFile string `yaml:"tls_ca_file,omitempty"`
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ type URLMap struct {
|
||||||
LoadBalancingPolicy string `yaml:"load_balancing_policy,omitempty"`
|
LoadBalancingPolicy string `yaml:"load_balancing_policy,omitempty"`
|
||||||
|
|
||||||
// DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend.
|
// DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend.
|
||||||
DropSrcPathPrefixParts int `yaml:"drop_src_path_prefix_parts,omitempty"`
|
DropSrcPathPrefixParts *int `yaml:"drop_src_path_prefix_parts,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regex represents a regex
|
// Regex represents a regex
|
||||||
|
@ -166,6 +166,9 @@ type URLPrefix struct {
|
||||||
|
|
||||||
// load balancing policy used
|
// load balancing policy used
|
||||||
loadBalancingPolicy string
|
loadBalancingPolicy string
|
||||||
|
|
||||||
|
// how many request path prefix parts to drop before routing the request to backendURL.
|
||||||
|
dropSrcPathPrefixParts int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *URLPrefix) setLoadBalancingPolicy(loadBalancingPolicy string) error {
|
func (up *URLPrefix) setLoadBalancingPolicy(loadBalancingPolicy string) error {
|
||||||
|
@ -606,17 +609,22 @@ func parseAuthConfigUsers(ac *AuthConfig) (map[string]*UserInfo, error) {
|
||||||
func (ui *UserInfo) initURLs() error {
|
func (ui *UserInfo) initURLs() error {
|
||||||
retryStatusCodes := defaultRetryStatusCodes.Values()
|
retryStatusCodes := defaultRetryStatusCodes.Values()
|
||||||
loadBalancingPolicy := *defaultLoadBalancingPolicy
|
loadBalancingPolicy := *defaultLoadBalancingPolicy
|
||||||
|
dropSrcPathPrefixParts := 0
|
||||||
if ui.URLPrefix != nil {
|
if ui.URLPrefix != nil {
|
||||||
if err := ui.URLPrefix.sanitize(); err != nil {
|
if err := ui.URLPrefix.sanitize(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(ui.RetryStatusCodes) > 0 {
|
if ui.RetryStatusCodes != nil {
|
||||||
retryStatusCodes = ui.RetryStatusCodes
|
retryStatusCodes = ui.RetryStatusCodes
|
||||||
}
|
}
|
||||||
if ui.LoadBalancingPolicy != "" {
|
if ui.LoadBalancingPolicy != "" {
|
||||||
loadBalancingPolicy = ui.LoadBalancingPolicy
|
loadBalancingPolicy = ui.LoadBalancingPolicy
|
||||||
}
|
}
|
||||||
|
if ui.DropSrcPathPrefixParts != nil {
|
||||||
|
dropSrcPathPrefixParts = *ui.DropSrcPathPrefixParts
|
||||||
|
}
|
||||||
ui.URLPrefix.retryStatusCodes = retryStatusCodes
|
ui.URLPrefix.retryStatusCodes = retryStatusCodes
|
||||||
|
ui.URLPrefix.dropSrcPathPrefixParts = dropSrcPathPrefixParts
|
||||||
if err := ui.URLPrefix.setLoadBalancingPolicy(loadBalancingPolicy); err != nil {
|
if err := ui.URLPrefix.setLoadBalancingPolicy(loadBalancingPolicy); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -638,16 +646,21 @@ func (ui *UserInfo) initURLs() error {
|
||||||
}
|
}
|
||||||
rscs := retryStatusCodes
|
rscs := retryStatusCodes
|
||||||
lbp := loadBalancingPolicy
|
lbp := loadBalancingPolicy
|
||||||
if len(e.RetryStatusCodes) > 0 {
|
dsp := dropSrcPathPrefixParts
|
||||||
|
if e.RetryStatusCodes != nil {
|
||||||
rscs = e.RetryStatusCodes
|
rscs = e.RetryStatusCodes
|
||||||
}
|
}
|
||||||
if e.LoadBalancingPolicy != "" {
|
if e.LoadBalancingPolicy != "" {
|
||||||
lbp = e.LoadBalancingPolicy
|
lbp = e.LoadBalancingPolicy
|
||||||
}
|
}
|
||||||
|
if e.DropSrcPathPrefixParts != nil {
|
||||||
|
dsp = *e.DropSrcPathPrefixParts
|
||||||
|
}
|
||||||
e.URLPrefix.retryStatusCodes = rscs
|
e.URLPrefix.retryStatusCodes = rscs
|
||||||
if err := e.URLPrefix.setLoadBalancingPolicy(lbp); err != nil {
|
if err := e.URLPrefix.setLoadBalancingPolicy(lbp); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
e.URLPrefix.dropSrcPathPrefixParts = dsp
|
||||||
}
|
}
|
||||||
if len(ui.URLMaps) == 0 && ui.URLPrefix == nil {
|
if len(ui.URLMaps) == 0 && ui.URLPrefix == nil {
|
||||||
return fmt.Errorf("missing `url_prefix`")
|
return fmt.Errorf("missing `url_prefix`")
|
||||||
|
|
|
@ -292,7 +292,7 @@ users:
|
||||||
TLSInsecureSkipVerify: &insecureSkipVerifyFalse,
|
TLSInsecureSkipVerify: &insecureSkipVerifyFalse,
|
||||||
RetryStatusCodes: []int{500, 501},
|
RetryStatusCodes: []int{500, 501},
|
||||||
LoadBalancingPolicy: "first_available",
|
LoadBalancingPolicy: "first_available",
|
||||||
DropSrcPathPrefixParts: 1,
|
DropSrcPathPrefixParts: intp(1),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -584,3 +584,7 @@ func mustParseURLs(us []string) *URLPrefix {
|
||||||
bus: bus,
|
bus: bus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func intp(n int) *int {
|
||||||
|
return &n
|
||||||
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ func processUserRequest(w http.ResponseWriter, r *http.Request, ui *UserInfo) {
|
||||||
|
|
||||||
func processRequest(w http.ResponseWriter, r *http.Request, ui *UserInfo) {
|
func processRequest(w http.ResponseWriter, r *http.Request, ui *UserInfo) {
|
||||||
u := normalizeURL(r.URL)
|
u := normalizeURL(r.URL)
|
||||||
up, hc, dropSrcPathPrefixParts := ui.getURLPrefixAndHeaders(u)
|
up, hc := ui.getURLPrefixAndHeaders(u)
|
||||||
isDefault := false
|
isDefault := false
|
||||||
if up == nil {
|
if up == nil {
|
||||||
if ui.DefaultURL == nil {
|
if ui.DefaultURL == nil {
|
||||||
|
@ -198,7 +198,7 @@ func processRequest(w http.ResponseWriter, r *http.Request, ui *UserInfo) {
|
||||||
query.Set("request_path", u.String())
|
query.Set("request_path", u.String())
|
||||||
targetURL.RawQuery = query.Encode()
|
targetURL.RawQuery = query.Encode()
|
||||||
} else { // Update path for regular routes.
|
} else { // Update path for regular routes.
|
||||||
targetURL = mergeURLs(targetURL, u, dropSrcPathPrefixParts)
|
targetURL = mergeURLs(targetURL, u, up.dropSrcPathPrefixParts)
|
||||||
}
|
}
|
||||||
ok := tryProcessingRequest(w, r, targetURL, hc, up.retryStatusCodes, ui.httpTransport)
|
ok := tryProcessingRequest(w, r, targetURL, hc, up.retryStatusCodes, ui.httpTransport)
|
||||||
bu.put()
|
bu.put()
|
||||||
|
|
|
@ -49,16 +49,16 @@ func dropPrefixParts(path string, parts int) string {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UserInfo) getURLPrefixAndHeaders(u *url.URL) (*URLPrefix, HeadersConf, int) {
|
func (ui *UserInfo) getURLPrefixAndHeaders(u *url.URL) (*URLPrefix, HeadersConf) {
|
||||||
for _, e := range ui.URLMaps {
|
for _, e := range ui.URLMaps {
|
||||||
if matchAnyRegex(e.SrcHosts, u.Host) && matchAnyRegex(e.SrcPaths, u.Path) {
|
if matchAnyRegex(e.SrcHosts, u.Host) && matchAnyRegex(e.SrcPaths, u.Path) {
|
||||||
return e.URLPrefix, e.HeadersConf, e.DropSrcPathPrefixParts
|
return e.URLPrefix, e.HeadersConf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ui.URLPrefix != nil {
|
if ui.URLPrefix != nil {
|
||||||
return ui.URLPrefix, ui.HeadersConf, ui.DropSrcPathPrefixParts
|
return ui.URLPrefix, ui.HeadersConf
|
||||||
}
|
}
|
||||||
return nil, HeadersConf{}, 0
|
return nil, HeadersConf{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchAnyRegex(rs []*Regex, s string) bool {
|
func matchAnyRegex(rs []*Regex, s string) bool {
|
||||||
|
|
|
@ -89,12 +89,12 @@ func TestCreateTargetURLSuccess(t *testing.T) {
|
||||||
t.Fatalf("cannot parse %q: %s", requestURI, err)
|
t.Fatalf("cannot parse %q: %s", requestURI, err)
|
||||||
}
|
}
|
||||||
u = normalizeURL(u)
|
u = normalizeURL(u)
|
||||||
up, hc, dropSrcPathPrefixParts := ui.getURLPrefixAndHeaders(u)
|
up, hc := ui.getURLPrefixAndHeaders(u)
|
||||||
if up == nil {
|
if up == nil {
|
||||||
t.Fatalf("cannot determie backend: %s", err)
|
t.Fatalf("cannot determie backend: %s", err)
|
||||||
}
|
}
|
||||||
bu := up.getLeastLoadedBackendURL()
|
bu := up.getLeastLoadedBackendURL()
|
||||||
target := mergeURLs(bu.url, u, dropSrcPathPrefixParts)
|
target := mergeURLs(bu.url, u, up.dropSrcPathPrefixParts)
|
||||||
bu.put()
|
bu.put()
|
||||||
if target.String() != expectedTarget {
|
if target.String() != expectedTarget {
|
||||||
t.Fatalf("unexpected target; got %q; want %q", target, expectedTarget)
|
t.Fatalf("unexpected target; got %q; want %q", target, expectedTarget)
|
||||||
|
@ -109,8 +109,8 @@ func TestCreateTargetURLSuccess(t *testing.T) {
|
||||||
if up.loadBalancingPolicy != expectedLoadBalancingPolicy {
|
if up.loadBalancingPolicy != expectedLoadBalancingPolicy {
|
||||||
t.Fatalf("unexpected loadBalancingPolicy; got %q; want %q", up.loadBalancingPolicy, expectedLoadBalancingPolicy)
|
t.Fatalf("unexpected loadBalancingPolicy; got %q; want %q", up.loadBalancingPolicy, expectedLoadBalancingPolicy)
|
||||||
}
|
}
|
||||||
if dropSrcPathPrefixParts != expectedDropSrcPathPrefixParts {
|
if up.dropSrcPathPrefixParts != expectedDropSrcPathPrefixParts {
|
||||||
t.Fatalf("unexpected dropSrcPathPrefixParts; got %d; want %d", dropSrcPathPrefixParts, expectedDropSrcPathPrefixParts)
|
t.Fatalf("unexpected dropSrcPathPrefixParts; got %d; want %d", up.dropSrcPathPrefixParts, expectedDropSrcPathPrefixParts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Simple routing with `url_prefix`
|
// Simple routing with `url_prefix`
|
||||||
|
@ -127,7 +127,7 @@ func TestCreateTargetURLSuccess(t *testing.T) {
|
||||||
},
|
},
|
||||||
RetryStatusCodes: []int{503, 501},
|
RetryStatusCodes: []int{503, 501},
|
||||||
LoadBalancingPolicy: "first_available",
|
LoadBalancingPolicy: "first_available",
|
||||||
DropSrcPathPrefixParts: 2,
|
DropSrcPathPrefixParts: intp(2),
|
||||||
}, "/a/b/c", "http://foo.bar/c", `[{"bb" "aaa"}]`, `[]`, []int{503, 501}, "first_available", 2)
|
}, "/a/b/c", "http://foo.bar/c", `[{"bb" "aaa"}]`, `[]`, []int{503, 501}, "first_available", 2)
|
||||||
f(&UserInfo{
|
f(&UserInfo{
|
||||||
URLPrefix: mustParseURL("http://foo.bar/federate"),
|
URLPrefix: mustParseURL("http://foo.bar/federate"),
|
||||||
|
@ -172,11 +172,13 @@ func TestCreateTargetURLSuccess(t *testing.T) {
|
||||||
},
|
},
|
||||||
RetryStatusCodes: []int{503, 500, 501},
|
RetryStatusCodes: []int{503, 500, 501},
|
||||||
LoadBalancingPolicy: "first_available",
|
LoadBalancingPolicy: "first_available",
|
||||||
DropSrcPathPrefixParts: 1,
|
DropSrcPathPrefixParts: intp(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SrcPaths: getRegexs([]string{"/api/v1/write"}),
|
SrcPaths: getRegexs([]string{"/api/v1/write"}),
|
||||||
URLPrefix: mustParseURL("http://vminsert/0/prometheus"),
|
URLPrefix: mustParseURL("http://vminsert/0/prometheus"),
|
||||||
|
RetryStatusCodes: []int{},
|
||||||
|
DropSrcPathPrefixParts: intp(0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
URLPrefix: mustParseURL("http://default-server"),
|
URLPrefix: mustParseURL("http://default-server"),
|
||||||
|
@ -191,13 +193,13 @@ func TestCreateTargetURLSuccess(t *testing.T) {
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
RetryStatusCodes: []int{502},
|
RetryStatusCodes: []int{502},
|
||||||
DropSrcPathPrefixParts: 2,
|
DropSrcPathPrefixParts: intp(2),
|
||||||
}
|
}
|
||||||
f(ui, "http://host42/vmsingle/api/v1/query?query=up", "http://vmselect/0/prometheus/api/v1/query?query=up",
|
f(ui, "http://host42/vmsingle/api/v1/query?query=up", "http://vmselect/0/prometheus/api/v1/query?query=up",
|
||||||
`[{"xx" "aa"} {"yy" "asdf"}]`, `[{"qwe" "rty"}]`, []int{503, 500, 501}, "first_available", 1)
|
`[{"xx" "aa"} {"yy" "asdf"}]`, `[{"qwe" "rty"}]`, []int{503, 500, 501}, "first_available", 1)
|
||||||
f(ui, "http://host123/vmsingle/api/v1/query?query=up", "http://default-server/v1/query?query=up",
|
f(ui, "http://host123/vmsingle/api/v1/query?query=up", "http://default-server/v1/query?query=up",
|
||||||
`[{"bb" "aaa"}]`, `[{"x" "y"}]`, []int{502}, "least_loaded", 2)
|
`[{"bb" "aaa"}]`, `[{"x" "y"}]`, []int{502}, "least_loaded", 2)
|
||||||
f(ui, "https://foo-host/api/v1/write", "http://vminsert/0/prometheus/api/v1/write", "[]", "[]", []int{502}, "least_loaded", 0)
|
f(ui, "https://foo-host/api/v1/write", "http://vminsert/0/prometheus/api/v1/write", "[]", "[]", []int{}, "least_loaded", 0)
|
||||||
f(ui, "https://foo-host/foo/bar/api/v1/query_range", "http://default-server/api/v1/query_range", `[{"bb" "aaa"}]`, `[{"x" "y"}]`, []int{502}, "least_loaded", 2)
|
f(ui, "https://foo-host/foo/bar/api/v1/query_range", "http://default-server/api/v1/query_range", `[{"bb" "aaa"}]`, `[{"x" "y"}]`, []int{502}, "least_loaded", 2)
|
||||||
|
|
||||||
// Complex routing regexp paths in `url_map`
|
// Complex routing regexp paths in `url_map`
|
||||||
|
@ -241,7 +243,7 @@ func TestCreateTargetURLFailure(t *testing.T) {
|
||||||
t.Fatalf("cannot parse %q: %s", requestURI, err)
|
t.Fatalf("cannot parse %q: %s", requestURI, err)
|
||||||
}
|
}
|
||||||
u = normalizeURL(u)
|
u = normalizeURL(u)
|
||||||
up, hc, dropSrcPathPrefixParts := ui.getURLPrefixAndHeaders(u)
|
up, hc := ui.getURLPrefixAndHeaders(u)
|
||||||
if up != nil {
|
if up != nil {
|
||||||
t.Fatalf("unexpected non-empty up=%#v", up)
|
t.Fatalf("unexpected non-empty up=%#v", up)
|
||||||
}
|
}
|
||||||
|
@ -251,9 +253,6 @@ func TestCreateTargetURLFailure(t *testing.T) {
|
||||||
if hc.ResponseHeaders != nil {
|
if hc.ResponseHeaders != nil {
|
||||||
t.Fatalf("unexpected non-empty response headers=%q", hc.ResponseHeaders)
|
t.Fatalf("unexpected non-empty response headers=%q", hc.ResponseHeaders)
|
||||||
}
|
}
|
||||||
if dropSrcPathPrefixParts != 0 {
|
|
||||||
t.Fatalf("unexpected non-zero dropSrcPathPrefixParts=%d", dropSrcPathPrefixParts)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
f(&UserInfo{}, "/foo/bar")
|
f(&UserInfo{}, "/foo/bar")
|
||||||
f(&UserInfo{
|
f(&UserInfo{
|
||||||
|
|
Loading…
Reference in a new issue