Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions promgen/prometheus.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
import subprocess
import tempfile
from urllib.parse import parse_qs, urljoin, urlparse
from urllib.parse import parse_qs, urlparse

import yaml
from dateutil import parser
Expand Down Expand Up @@ -335,7 +335,7 @@ def silence(*, labels, duration=None, **kwargs):
]

logger.debug("Sending silence for %s", kwargs)
url = urljoin(util.setting("alertmanager:url"), "/api/v2/silences")
url = util.join_url(util.setting("alertmanager:url"), "/api/v2/silences")
response = util.post(url, json=kwargs)
response.raise_for_status()
return response
9 changes: 4 additions & 5 deletions promgen/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import json
import logging
from http import HTTPStatus
from urllib.parse import urljoin

import requests
from django.http import HttpResponse, JsonResponse
Expand Down Expand Up @@ -47,7 +46,7 @@ def proxy(self, request):
futures.append(
executor.submit(
util.get,
urljoin(shard.url, request.get_full_path_info()),
util.join_url(shard.url, request.get_full_path_info()),
headers=headers,
)
)
Expand Down Expand Up @@ -160,7 +159,7 @@ def get(self, request):
class ProxyAlerts(View):
def get(self, request):
try:
url = urljoin(util.setting("alertmanager:url"), "/api/v2/alerts")
url = util.join_url(util.setting("alertmanager:url"), "/api/v2/alerts")
response = util.get(url)
except requests.exceptions.ConnectionError:
logger.error("Error connecting to %s", url)
Expand Down Expand Up @@ -270,7 +269,7 @@ def get_queryset_for_matcher(matcher, klass):
class ProxySilences(View):
def get(self, request):
try:
url = urljoin(util.setting("alertmanager:url"), "/api/v2/silences")
url = util.join_url(util.setting("alertmanager:url"), "/api/v2/silences")
response = util.get(url, params={"silenced": False})
except requests.exceptions.ConnectionError:
logger.error("Error connecting to %s", url)
Expand Down Expand Up @@ -491,7 +490,7 @@ def post(self, request, *args, **kwargs):

class ProxyDeleteSilence(View):
def delete(self, request, silence_id):
url = urljoin(util.setting("alertmanager:url"), f"/api/v2/silence/{silence_id}")
url = util.join_url(util.setting("alertmanager:url"), f"/api/v2/silence/{silence_id}")
# First, check if the silence exists
response = util.get(url)
if response.status_code != 200:
Expand Down
5 changes: 2 additions & 3 deletions promgen/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import os
import socket
from datetime import datetime
from urllib.parse import urljoin

from atomicwrites import atomic_write
from billiard.exceptions import SoftTimeLimitExceeded
Expand Down Expand Up @@ -184,15 +183,15 @@ def send_notification(*args, alert_pk, **kwargs):
def reload_prometheus():
from promgen import signals

target = urljoin(util.setting("prometheus:url"), "/-/reload")
target = util.join_url(util.setting("prometheus:url"), "/-/reload")
response = util.post(target)
response.raise_for_status()
signals.post_reload.send(response)


@shared_task(base=BaseTaskWithRetry)
def clear_tombstones():
target = urljoin(util.setting("prometheus:url"), "/api/v1/admin/tsdb/clean_tombstones")
target = util.join_url(util.setting("prometheus:url"), "/api/v1/admin/tsdb/clean_tombstones")
response = util.post(target)
response.raise_for_status()

Expand Down
25 changes: 25 additions & 0 deletions promgen/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,28 @@ def test_categorize_error(self):
for error, expected in cases:
with self.subTest(error=type(error).__name__, expected=expected):
self.assertEqual(util.categorize_error(error), expected)

def test_join_url(self):
cases = [
("http://prometheus:9090", "/-/reload", "http://prometheus:9090/-/reload"),
("http://prometheus:9090/", "/-/reload", "http://prometheus:9090/-/reload"),
(
"http://example.com/prometheus",
"/-/reload",
"http://example.com/prometheus/-/reload",
),
(
"http://example.com/prometheus/",
"/api/v1/query?query=up",
"http://example.com/prometheus/api/v1/query?query=up",
),
(
"http://example.com/alertmanager/",
"api/v2/silences",
"http://example.com/alertmanager/api/v2/silences",
),
]

for base, path, expected in cases:
with self.subTest(base=base, path=path):
self.assertEqual(util.join_url(base, path), expected)
7 changes: 7 additions & 0 deletions promgen/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ def scrape(url, params=None, **kwargs):
return requests.get(url, params=params, **kwargs)


def join_url(base, path):
"""
Append a path to a base URL, keeping any path prefix of the base URL
"""
return f"{base.removesuffix('/')}/{path.removeprefix('/')}"


def setting(key, default=None, domain=None):
"""
Settings helper based on saltstack's query
Expand Down