allow headers to be added to prometheus requests

Signed-off-by: Nick Otter <otternq@gmail.com>
Co-authored-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
This commit is contained in:
Nick Otter 2025-01-14 18:07:35 +00:00 committed by Sanskar Jaiswal
parent f21bc1de3e
commit 8f9bb5b1bc
No known key found for this signature in database
GPG Key ID: 5982D0279C227FFD
7 changed files with 86 additions and 0 deletions

View File

@ -1313,6 +1313,13 @@ spec:
address:
description: API address of this provider
type: string
headers:
description: Headers to add to HTTP(S) requests
type: object
additionalProperties:
type: array
items:
type: string
secretRef:
description: Kubernetes secret reference containing the provider credentials
type: object

View File

@ -1313,6 +1313,13 @@ spec:
address:
description: API address of this provider
type: string
headers:
description: Headers to add to HTTP(S) requests
type: object
additionalProperties:
type: array
items:
type: string
secretRef:
description: Kubernetes secret reference containing the provider credentials
type: object

View File

@ -1313,6 +1313,13 @@ spec:
address:
description: API address of this provider
type: string
headers:
description: Headers to add to HTTP(S) requests
type: object
additionalProperties:
type: array
items:
type: string
secretRef:
description: Kubernetes secret reference containing the provider credentials
type: object

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1beta1
import (
"net/http"
"text/template"
corev1 "k8s.io/api/core/v1"
@ -67,6 +68,10 @@ type MetricTemplateProvider struct {
// +optional
Address string `json:"address,omitempty"`
// Headers to be supplied to HTTP(S) request of this provider
// +optional
Headers http.Header `json:"headers,omitempty"`
// Secret reference containing the provider credentials
// +optional
SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"`

View File

@ -22,6 +22,8 @@ limitations under the License.
package v1beta1
import (
http "net/http"
gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
v1 "k8s.io/api/core/v1"
@ -810,6 +812,21 @@ func (in *MetricTemplateModel) DeepCopy() *MetricTemplateModel {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MetricTemplateProvider) DeepCopyInto(out *MetricTemplateProvider) {
*out = *in
if in.Headers != nil {
in, out := &in.Headers, &out.Headers
*out = make(http.Header, len(*in))
for key, val := range *in {
var outVal []string
if val == nil {
(*out)[key] = nil
} else {
in, out := &val, &outVal
*out = make([]string, len(*in))
copy(*out, *in)
}
(*out)[key] = outVal
}
}
if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef
*out = new(v1.LocalObjectReference)

View File

@ -39,6 +39,7 @@ const prometheusOnlineQuery = "vector(1)"
type PrometheusProvider struct {
timeout time.Duration
url url.URL
headers http.Header
username string
password string
token string
@ -69,6 +70,7 @@ func NewPrometheusProvider(provider flaggerv1.MetricTemplateProvider, credential
prom := PrometheusProvider{
timeout: 5 * time.Second,
url: *promURL,
headers: provider.Headers,
client: http.DefaultClient,
}
@ -116,6 +118,10 @@ func (p *PrometheusProvider) RunQuery(query string) (float64, error) {
return 0, fmt.Errorf("http.NewRequest failed: %w", err)
}
if p.headers != nil {
req.Header = p.headers
}
if p.token != "" {
req.Header.Add("Authorization", "Bearer "+p.token)
} else if p.username != "" && p.password != "" {

View File

@ -307,3 +307,40 @@ func TestPrometheusProvider_IsOnline(t *testing.T) {
assert.Equal(t, true, ok)
})
}
func TestPrometheusProvider_RunQueryWithProviderHeaders(t *testing.T) {
t.Run("ok", func(t *testing.T) {
expected := `sum(envoy_cluster_upstream_rq)`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
promql := r.URL.Query()["query"][0]
assert.Equal(t, expected, promql)
assert.Equal(t, []string{"tenant1"}, r.Header.Values("X-Scope-Orgid"))
json := `{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1545905245.458,"100"]}]}}`
w.Write([]byte(json))
}))
defer ts.Close()
clients := prometheusFake()
template, err := clients.flaggerClient.FlaggerV1beta1().MetricTemplates("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
template.Spec.Provider.Address = ts.URL
template.Spec.Provider.Headers = http.Header{
"X-Scope-OrgID": []string{"tenant1"},
}
secret, err := clients.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
prom, err := NewPrometheusProvider(template.Spec.Provider, secret.Data)
require.NoError(t, err)
val, err := prom.RunQuery(template.Spec.Query)
require.NoError(t, err)
assert.Equal(t, float64(100), val)
})
}