Initial commit
This commit is contained in:
parent
1aac33ec47
commit
8a691b0cf7
258
libexec/agent_traefik
Executable file
258
libexec/agent_traefik
Executable file
@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=too-many-instance-attributes, pointless-string-statement
|
||||
"""CheckMK Special Agent for Traefik"""
|
||||
|
||||
import time
|
||||
import argparse
|
||||
from typing import Dict, Union, Optional, Final
|
||||
|
||||
import requests
|
||||
import urllib3
|
||||
from requests.auth import HTTPDigestAuth, HTTPBasicAuth
|
||||
|
||||
# dictionary with all parameters
|
||||
ArgumentsMap = Dict[str, Union[str, bool, None]]
|
||||
|
||||
TIMEOUT: Final[int] = 30
|
||||
NOT_AVAIL: Final[str] = "N/A"
|
||||
|
||||
|
||||
class TraefikAPI:
|
||||
"""Traefik API Class"""
|
||||
|
||||
def __init__(self, args: ArgumentsMap):
|
||||
"""Initialize TraefikAPI"""
|
||||
self.start_time: float = time.perf_counter()
|
||||
# set arguments
|
||||
self.hostname: str = args.get("hostname")
|
||||
self.username: str = args.get("username")
|
||||
self.password: str = args.get("password")
|
||||
self.auth_type: str = args.get("auth_type")
|
||||
self.no_http_check: bool = args.get("no_http_check", False)
|
||||
self.no_tcp_check: bool = args.get("no_tcp_check", False)
|
||||
self.no_udp_check: bool = args.get("no_udp_check", False)
|
||||
self.no_cert_check: bool = args.get("no_cert_check", False)
|
||||
self.no_https: bool = args.get("no_https", False)
|
||||
# define other attributes
|
||||
if self.no_cert_check:
|
||||
# disable certificate warnings
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
self.verify = False
|
||||
else:
|
||||
self.verify = True
|
||||
if self.no_https:
|
||||
self.protocol = "http"
|
||||
self.port = "80"
|
||||
else:
|
||||
self.protocol = "https"
|
||||
self.port = "443"
|
||||
if args.get("port"):
|
||||
self.port = args.get("port")
|
||||
|
||||
self.base_url: str = f"{self.protocol}://{self.hostname}:{self.port}/api"
|
||||
# print(f"Base URL: {self.base_url}")
|
||||
self.session: Optional[requests.Session] = None
|
||||
self.overview: Optional[dict] = None
|
||||
|
||||
def __enter__(self):
|
||||
self.session: requests.Session = requests.Session()
|
||||
if self.auth_type == "basic":
|
||||
self.session.auth = HTTPBasicAuth(self.username, self.password)
|
||||
elif self.auth_type == "digest":
|
||||
self.session.auth = HTTPDigestAuth(self.username, self.password)
|
||||
else:
|
||||
print(
|
||||
f"Error: Invalid authentication type '{self.auth_type}'. Use 'basic' or 'digest'."
|
||||
)
|
||||
return None
|
||||
return self
|
||||
|
||||
def __exit__(self, _exc_type, _exc_value, _traceback) -> None:
|
||||
if self.session:
|
||||
self.session.close()
|
||||
end_time: float = time.perf_counter()
|
||||
duration: float = end_time - self.start_time
|
||||
traefik_info: Optional[dict] = self._get_version()
|
||||
if traefik_info:
|
||||
print("<<<traefik_info:sep(59)>>>")
|
||||
print(traefik_info.get("Version", NOT_AVAIL))
|
||||
print(traefik_info.get("Codename", NOT_AVAIL))
|
||||
print(traefik_info.get("startDate", NOT_AVAIL))
|
||||
print(duration)
|
||||
|
||||
def _get_version(self) -> Optional[dict]:
|
||||
"""Get data from API endpoint version"""
|
||||
try:
|
||||
response: requests.Response = self.session.get(
|
||||
f"{self.base_url}/version", timeout=TIMEOUT, verify=self.verify
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
print(f"Error fetching version data: {e}")
|
||||
return None
|
||||
|
||||
def get_overview(self) -> Optional[dict]:
|
||||
"""Get data from API endpoint overview"""
|
||||
try:
|
||||
response: requests.Response = self.session.get(
|
||||
f"{self.base_url}/overview", timeout=TIMEOUT, verify=self.verify
|
||||
)
|
||||
response.raise_for_status()
|
||||
self.overview = response.json()
|
||||
return self.overview
|
||||
except requests.RequestException as e:
|
||||
print(f"Error fetching overview data: {e}")
|
||||
return None
|
||||
|
||||
def create_section_output(self) -> None:
|
||||
"""Create section output"""
|
||||
total: int = 0
|
||||
warnings: int = 0
|
||||
errors: int = 0
|
||||
data: dict[str, dict[str, int]] = {}
|
||||
|
||||
if not self.no_http_check:
|
||||
print("<<<traefik_http_components:sep(59)>>>")
|
||||
# Process HTTP components
|
||||
data = self.overview.get("http", {})
|
||||
for component in ["routers", "services", "middlewares"]:
|
||||
total = data.get(component, {}).get("total", -1)
|
||||
warnings = data.get(component, {}).get("warnings", -1)
|
||||
errors = data.get(component, {}).get("errors", -1)
|
||||
print(f"{component};{total};{warnings};{errors}")
|
||||
if not self.no_tcp_check:
|
||||
print("<<<traefik_tcp_components:sep(59)>>>")
|
||||
# Process TCP components
|
||||
data = self.overview.get("tcp", {})
|
||||
for component in ["routers", "services", "middlewares"]:
|
||||
total = data.get(component, {}).get("total", -1)
|
||||
warnings = data.get(component, {}).get("warnings", -1)
|
||||
errors = data.get(component, {}).get("errors", -1)
|
||||
print(f"{component};{total};{warnings};{errors}")
|
||||
if not self.no_udp_check:
|
||||
print("<<<traefik_udp_components:sep(59)>>>")
|
||||
# Process UDP components
|
||||
data = self.overview.get("udp", {})
|
||||
for component in ["routers", "services"]:
|
||||
total = data.get(component, {}).get("total", -1)
|
||||
warnings = data.get(component, {}).get("warnings", -1)
|
||||
errors = data.get(component, {}).get("errors", -1)
|
||||
print(f"{component};{total};{warnings};{errors}")
|
||||
|
||||
|
||||
def parse_arguments() -> ArgumentsMap:
|
||||
"""Parse command-line arguments"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Parameters to connect to the API of a Traefik instance",
|
||||
)
|
||||
# Required arguments
|
||||
parser.add_argument(
|
||||
"--hostname",
|
||||
type=str,
|
||||
required=True,
|
||||
help="The hostname (FQDN) or IP address of the Traefik instance.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--username",
|
||||
type=str,
|
||||
required=True,
|
||||
help="The username for authentication.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--password",
|
||||
type=str,
|
||||
required=True,
|
||||
help="The password for authentication.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--auth-type",
|
||||
type=str,
|
||||
required=True,
|
||||
choices=["basic", "digest"], # Restrict allowed values
|
||||
help="The authentication type to use ('basic' or 'digest').",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-http-check",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Disable HTTP components check (optional, default=no).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-tcp-check",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Disable TCP components check (optional, default=no).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-udp-check",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Disable UDP components check (optional, default=no).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-cert-check",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Disable certificate check (optional, default=no).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-https",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Disable HTTPS (optional, default=no).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--port",
|
||||
type=int,
|
||||
required=False,
|
||||
help="Port if not listening to HTTP(S) on default ports 80/443 (optional).",
|
||||
)
|
||||
args: argparse.Namespace = parser.parse_args()
|
||||
arg_map: ArgumentsMap = vars(args)
|
||||
return arg_map
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Main function"""
|
||||
args: ArgumentsMap = parse_arguments()
|
||||
with TraefikAPI(args=args) as traefik:
|
||||
overview = traefik.get_overview()
|
||||
if overview:
|
||||
traefik.create_section_output()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
"""
|
||||
|
||||
Sample output
|
||||
component;total number of components;number of warnings;number of errors
|
||||
|
||||
<<<traefik_http_components:sep(59)>>>
|
||||
routers;50;0;0
|
||||
services;52;0;0
|
||||
middlewares;5;0;0
|
||||
<<<traefik_tcp_components:sep(59)>>>
|
||||
routers;1;0;0
|
||||
services;1;0;0
|
||||
middlewares;0;0;0
|
||||
<<<traefik_udp_components:sep(59)>>>
|
||||
routers;0;0;0
|
||||
services;0;0;0
|
||||
|
||||
## General Traefik info
|
||||
Lines contain
|
||||
Version
|
||||
Codename
|
||||
Start Date
|
||||
Runtime of script (in seconds)
|
||||
|
||||
<<<traefik_info:sep(59)>>>
|
||||
3.3.5
|
||||
saintnectaire
|
||||
2025-04-18T19:01:01.706796728+02:00
|
||||
0.19748995700501837
|
||||
|
||||
"""
|
Loading…
x
Reference in New Issue
Block a user