-
Notifications
You must be signed in to change notification settings - Fork 0
feat(runner/prometheus): PROMETHEUS_AUTH, URL query string, retention fallback #526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -62,11 +62,16 @@ type Proxy struct { | |||||
| PrometheusURL string | ||||||
|
|
||||||
| // PrometheusHeaders is the parsed PROMETHEUS_HEADERS env (raw | ||||||
| // "Header: value, Header: value" string) — applied to every | ||||||
| // "Header: value; Header: value" string) — applied to every | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment describes
Suggested change
|
||||||
| // Prometheus proxy request so X-Scope-OrgID / tenant headers reach | ||||||
| // the upstream. Same shape ExtraHeaders uses for Grafana. | ||||||
| // the upstream. Same shape ExtraHeaders uses for Grafana. When | ||||||
| // PROMETHEUS_AUTH is set the caller overlays it here as Authorization. | ||||||
| PrometheusHeaders http.Header | ||||||
|
|
||||||
| // PrometheusQueryString (PROMETHEUS_URL_QUERY_STRING) is appended to the | ||||||
| // query string of every proxied Prometheus request. Empty is a no-op. | ||||||
| PrometheusQueryString string | ||||||
|
|
||||||
| // Username/Password for Grafana basic auth (GRAFANA_USERNAME / | ||||||
| // GRAFANA_PASSWORD env). Empty disables. | ||||||
| Username string | ||||||
|
|
@@ -134,7 +139,23 @@ func (p *Proxy) HandlePrometheus(ctx context.Context, req *Request) *Response { | |||||
| } | ||||||
| enriched := *req | ||||||
| enriched.Header = mergeHeaders(req.Header, p.PrometheusHeaders) | ||||||
| return p.do(ctx, p.PrometheusURL+req.URL, &enriched) | ||||||
| return p.do(ctx, appendQueryString(p.PrometheusURL+req.URL, p.PrometheusQueryString), &enriched) | ||||||
| } | ||||||
|
|
||||||
| // appendQueryString appends extra (a "k=v&k2=v2" fragment, optional leading | ||||||
| // "?") to rawurl's query, using "?" or "&" depending on whether rawurl already | ||||||
| // has a query. Empty extra is a no-op. | ||||||
| func appendQueryString(rawurl, extra string) string { | ||||||
| extra = strings.TrimSpace(extra) | ||||||
| extra = strings.TrimPrefix(extra, "?") | ||||||
| if extra == "" { | ||||||
| return rawurl | ||||||
| } | ||||||
| sep := "?" | ||||||
| if strings.Contains(rawurl, "?") { | ||||||
| sep = "&" | ||||||
| } | ||||||
| return rawurl + sep + extra | ||||||
| } | ||||||
|
|
||||||
| // mergeHeaders returns a new header map containing every entry from | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,8 +37,13 @@ type Client struct { | |
| // ExtraHeaders are sent on every request. Used for X-Scope-OrgID | ||
| // (Cortex/Mimir multi-tenant) and any auth headers the operator | ||
| // configures via the runner secret today (LOKI_EXTRA_HEADER pattern). | ||
| // PROMETHEUS_AUTH is delivered here as an Authorization header. | ||
| ExtraHeaders http.Header | ||
|
|
||
| // URLQueryString (PROMETHEUS_URL_QUERY_STRING) is appended to the query | ||
| // string of every request. Empty is a no-op. Leading "?" is optional. | ||
| URLQueryString string | ||
|
|
||
| // Auth applies a managed-provider auth scheme (AWS SigV4 / Azure AD / | ||
| // Coralogix) to each request. Nil when the backend uses plain headers | ||
| // or no auth. See auth.go. | ||
|
|
@@ -171,6 +176,22 @@ func (c *Client) Flags(ctx context.Context) (json.RawMessage, error) { | |
| return c.get(ctx, "/api/v1/status/flags", nil) | ||
| } | ||
|
|
||
| // appendQueryString appends extra (a "k=v&k2=v2" fragment, with an optional | ||
| // leading "?") to rawurl's query, choosing "?" or "&" based on whether | ||
| // rawurl already has a query. Empty extra is a no-op. | ||
| func appendQueryString(rawurl, extra string) string { | ||
| extra = strings.TrimSpace(extra) | ||
| extra = strings.TrimPrefix(extra, "?") | ||
| if extra == "" { | ||
| return rawurl | ||
| } | ||
| sep := "?" | ||
| if strings.Contains(rawurl, "?") { | ||
| sep = "&" | ||
| } | ||
| return rawurl + sep + extra | ||
| } | ||
|
Comment on lines
+182
to
+193
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using manual string manipulation to append query parameters can be fragile (e.g., if the URL already ends with func appendQueryString(rawurl, extra string) string {
extra = strings.TrimSpace(extra)
extra = strings.TrimPrefix(extra, "?")
if extra == "" {
return rawurl
}
u, err := url.Parse(rawurl)
if err != nil {
sep := "?"
if strings.Contains(rawurl, "?") {
sep = "&"
}
return rawurl + sep + extra
}
if u.RawQuery == "" {
u.RawQuery = extra
} else {
u.RawQuery += "&" + extra
}
return u.String()
} |
||
|
|
||
| func (c *Client) get(ctx context.Context, path string, params url.Values) (json.RawMessage, error) { | ||
| if c.BaseURL == "" { | ||
| return nil, errors.New("prometheus: base URL not configured") | ||
|
|
@@ -179,6 +200,7 @@ func (c *Client) get(ctx context.Context, path string, params url.Values) (json. | |
| if len(params) > 0 { | ||
| u += "?" + params.Encode() | ||
| } | ||
| u = appendQueryString(u, c.URLQueryString) | ||
| req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) | ||
| if err != nil { | ||
| return nil, err | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states that
PROMETHEUS_HEADERSis semicolon-separated, but the underlying parserconfig.ParseHeadersinrunner/pkg/config/config.gosplits headers by commas (,):If users configure this variable using semicolons, it will fail to parse correctly (e.g., the second header will be treated as part of the first header's value). Please revert this to 'Comma-separated' or update the parser to support semicolons.