diff --git a/promgen/migrations/0023_shard_authorization.py b/promgen/migrations/0023_shard_authorization.py new file mode 100644 index 000000000..7087383ca --- /dev/null +++ b/promgen/migrations/0023_shard_authorization.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.11 on 2024-06-28 09:57 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("promgen", "0022_rule_labels_annotations"), + ] + + operations = [ + migrations.AddField( + model_name="shard", + name="authorization", + field=models.CharField( + blank=True, + help_text="HTTP Authorization header for this shard's API", + max_length=4083, + null=True, + ), + ), + ] diff --git a/promgen/models.py b/promgen/models.py index 03bd89cc0..27330f296 100644 --- a/promgen/models.py +++ b/promgen/models.py @@ -172,6 +172,12 @@ class Meta: class Shard(models.Model): name = models.CharField(max_length=128, unique=True, validators=[validators.labelvalue]) url = models.URLField(max_length=256) + authorization = models.CharField( + max_length=4083, # 4KB - len("authorization") + blank=True, + null=True, + help_text="HTTP Authorization header for this shard's API", + ) proxy = models.BooleanField( default=False, help_text="Queries can be proxied to these shards", diff --git a/promgen/proxy.py b/promgen/proxy.py index 3ace74422..6eaee9eb7 100644 --- a/promgen/proxy.py +++ b/promgen/proxy.py @@ -39,7 +39,7 @@ class PrometheusProxy(View): proxy_headers = {"HTTP_REFERER": "Referer"} @property - def headers(self): + def request_headers(self): # Loop through the headers from our request, and decide which ones # we should pass through upstream. Currently, our 'Referer' header is # the main one we are interested in, since this can help us debug which @@ -53,12 +53,15 @@ def headers(self): def proxy(self, request): futures = [] with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor: - for host in models.Shard.objects.filter(proxy=True): + for shard in models.Shard.objects.filter(proxy=True): + headers = self.request_headers + if shard.authorization: + headers["Authorization"] = shard.authorization futures.append( executor.submit( util.get, - urljoin(host.url, request.get_full_path_info()), - headers=self.headers, + urljoin(shard.url, request.get_full_path_info()), + headers=headers, ) ) yield from concurrent.futures.as_completed(futures) diff --git a/promgen/static/js/promgen.vue.js b/promgen/static/js/promgen.vue.js index e9410cc63..be3d63ab8 100644 --- a/promgen/static/js/promgen.vue.js +++ b/promgen/static/js/promgen.vue.js @@ -234,7 +234,7 @@ app.component('silence-modal', { app.component("promql-query", { delimiters: ['[[', ']]'], - props: ["href", "query", "max"], + props: ["shard", "query", "max"], data: function () { return { count: 0, @@ -256,9 +256,11 @@ app.component("promql-query", { }, template: '#promql-query-template', mounted() { - var url = new URL(this.href); - url.search = new URLSearchParams({ query: this.query }); - fetch(url) + const params = new URLSearchParams({ + shard: this.shard, + query: this.query, + }); + fetch(`/promql-query?${params}`) .then(response => response.json()) .then(result => this.count = Number.parseInt(result.data.result[0].value[1])) .finally(() => this.ready = true); diff --git a/promgen/templates/promgen/project_form.html b/promgen/templates/promgen/project_form.html index edf758a03..15cad6127 100644 --- a/promgen/templates/promgen/project_form.html +++ b/promgen/templates/promgen/project_form.html @@ -87,10 +87,10 @@