v1.9.40: Grafana basic auth support (user/password + api_token)

- Add user/password fields to Grafana in server dialog FIELD_MAP
- GrafanaClient: support basic auth when no api_token is set
- ssh.py: _grafana_request supports basic auth fallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-03-06 10:04:09 -05:00
parent df40af5632
commit d49fa9ce90
5 changed files with 24 additions and 15 deletions

View File

@@ -20,19 +20,25 @@ class GrafanaClient:
Initialize the Grafana client.
Args:
server: dict with keys: ip, port, api_token, use_ssl
server: dict with keys: ip, port, api_token (or user+password), use_ssl
"""
self.ip: str = server["ip"]
self.port: int = int(server["port"])
self.api_token: str = server["api_token"]
self.api_token: str = server.get("api_token", "")
self.user: str = server.get("user", "")
self.password: str = server.get("password", "")
self.use_ssl: bool = bool(server.get("use_ssl", False))
scheme = "https" if self.use_ssl else "http"
self.base_url: str = f"{scheme}://{self.ip}:{self.port}"
self.headers: dict[str, str] = {
"Authorization": f"Bearer {self.api_token}",
"Content-Type": "application/json",
}
self.headers: dict[str, str] = {"Content-Type": "application/json"}
self.auth: tuple[str, str] | None = None
if self.api_token:
self.headers["Authorization"] = f"Bearer {self.api_token}"
elif self.user and self.password:
self.auth = (self.user, self.password)
self.timeout: int = 10
def _get(self, path: str, params: dict | None = None) -> Any:
@@ -42,7 +48,7 @@ class GrafanaClient:
url = f"{self.base_url}{path}"
log.debug("Grafana GET %s", url)
resp = requests.get(
url, headers=self.headers, params=params, timeout=self.timeout
url, headers=self.headers, params=params, auth=self.auth, timeout=self.timeout
)
resp.raise_for_status()
return resp.json()
@@ -54,7 +60,7 @@ class GrafanaClient:
url = f"{self.base_url}{path}"
log.debug("Grafana POST %s", url)
resp = requests.post(
url, headers=self.headers, json=json_data, timeout=self.timeout
url, headers=self.headers, json=json_data, auth=self.auth, timeout=self.timeout
)
resp.raise_for_status()
return resp.json()