Source code for pretiac.config

import os
from pathlib import Path
from typing import Literal, Optional, Sequence, Union

import yaml
from pydantic import TypeAdapter
from pydantic.dataclasses import dataclass

from pretiac.exceptions import PretiacException
from pretiac.object_types import Payload


[docs] @dataclass(config={"extra": "forbid"}) class ObjectConfig: """ Bundles all configuration required to create an object. """ templates: Optional[Sequence[str]] = None """ Import existing configuration templates for this object type. Note: These templates must either be statically configured or provided in config packages. """ attrs: Optional["Payload"] = None """Set specific object attributes for this object type."""
[docs] @dataclass(config={"extra": "forbid"}) class Config: """ :see: `pretiac (JS) <https://github.com/Josef-Friedrich/PREtty-Typed-Icinga2-Api-Client_js/blob/722c6308d79f603a9ad7678609cd907b932c64ab/src/client.ts#L7-L15>`__ """ config_file: Optional[Path] = None """The path of the loaded configuration file.""" api_endpoint_host: Optional[str] = None """ The domain or the IP address of the API endpoint, e. g. ``icinga.example.com``, ``localhost`` or ``127.0.0.1``. """ api_endpoint_port: Optional[int] = None """The TCP port of the API endpoint, for example ``5665``. :see: `Icinca Object Types (apilistener) <https://icinga.com/docs/icinga-2/latest/doc/09-object-types/#apilistener>`__ """ http_basic_username: Optional[str] = None """ The name of the API user used in the HTTP basic authentification, e. g. ``apiuser``. .. code-block :: object ApiUser "apiuser" { ... } :see: `Icinca Object Types (apiuser) <https://icinga.com/docs/icinga-2/latest/doc/09-object-types/#apiuser>`__ """ http_basic_password: Optional[str] = None """ The password of the API user used in the HTTP basic authentification, e. g. ``password``. .. code-block :: object ApiUser "apiuser" { password = "password" } :see: `Icinca Object Types <https://icinga.com/docs/icinga-2/latest/doc/09-object-types/#apiuser>`__ """ client_private_key: Optional[str] = None """ The file path of the client’s **private RSA key**, for example ``/etc/pretiac/api-client.key.pem``. The RSA private key is created with this command: .. code-block :: icinga2 pki new-cert \\ --cn api-client \\ --key api-client.key.pem \\ --csr api-client.csr.pem """ client_certificate: Optional[str] = None """ The file path of the client **certificate**. The certificate is created with this command: .. code-block :: icinga2 pki sign-csr \\ --csr api-client.csr.pem \\ --cert api-client.cert.pem """ ca_certificate: Optional[str] = None """ The file path of the Icinga **CA (Certification Authority)**. The CA certificate is located at ``/var/lib/icinga2/certs/ca.crt``. This command copies the certificate to the local host. .. code-block :: scp icinga-master:/var/lib/icinga2/certs/ca.crt . """ suppress_exception: Optional[bool] = None """ If set to ``True``, no exceptions are thrown. """ new_host_defaults: Optional[ObjectConfig] = None """If a new host needs to be created, use this defaults.""" new_service_defaults: Optional[ObjectConfig] = None """If a new service needs to be created, use this defaults."""
[docs] def check(self) -> None: """Check if all required values are set.""" if self.api_endpoint_host is None: raise PretiacException("Specify an API endpoint host (api_endpoint_host)!") if (self.http_basic_username or self.http_basic_password) and ( self.client_private_key or self.client_certificate or self.ca_certificate ): raise PretiacException( "Specify HTTP basic OR certificate authentification. Not both!" )
[docs] def load_config_file(config_file: Optional[Union[str, Path]] = None) -> Config: """ Load the configuration file in YAML format. The file path of the loaded configuration file is determined in this order: 1. The parameter ``config_file`` of this function. 2. The file path in the environment variable ``PRETIAC_CONFIG_FILE``. 3. The configuration file in the home folder ``~/.pretiac.yml``. 4. The configuration file at ``/etc/pretiac/config.yml``. :param config_file: The path of the configuration file to load. """ config_files: list[Path] = [] if config_file: if isinstance(config_file, str): config_files.append(Path(config_file)) else: config_files.append(config_file) if "PRETIAC_CONFIG_FILE" in os.environ: config_files.append(Path(os.environ["PRETIAC_CONFIG_FILE"])) config_files.append(Path.cwd() / ".pretiac.yml") config_files.append(Path("/etc/pretiac/config.yml")) for path in config_files: if path.exists(): config_file = path break adapter = TypeAdapter(Config) if not config_file: return adapter.validate_python({}) with open(config_file, "r") as file: config_raw = yaml.safe_load(file) config_raw["config_file"] = str(config_file) return adapter.validate_python(config_raw)
[docs] def load_config( config: Optional[Config] = None, config_file: Optional[Union[str, Path, Literal[False]]] = None, api_endpoint_host: Optional[str] = None, api_endpoint_port: Optional[int] = None, http_basic_username: Optional[str] = None, http_basic_password: Optional[str] = None, client_private_key: Optional[str] = None, client_certificate: Optional[str] = None, ca_certificate: Optional[str] = None, suppress_exception: Optional[bool] = None, new_host_defaults: Optional[ObjectConfig] = None, new_service_defaults: Optional[ObjectConfig] = None, ) -> Config: """ :param config: A configuration object that has already been populated. :param config_file: The path of the configuration file to load. If this value is set to false no configuration file will be loaded. :param api_endpoint_host: The domain or the IP address of the API endpoint, e. g. ``icinga.example.com``, ``localhost`` or ``127.0.0.1``. :param api_endpoint_port: The TCP port of the API endpoint, for example ``5665``. :param http_basic_username: The name of the API user used in the HTTP basic authentification, e. g. ``apiuser``. :param http_basic_password: The password of the API user used in the HTTP basic authentification, e. g. ``password``. :param client_private_key: The file path of the client’s **private RSA key**, for example ``/etc/pretiac/api-client.key.pem``. :param client_certificate: The file path of the client’s **certificate**, for example ``/etc/pretiac/api-client.cert.pem``. :param ca_certificate: The file path of the Icinga **CA (Certification Authority)**, for example ``/var/lib/icinga2/certs/ca.crt``. :param suppress_exception: If set to ``True``, no exceptions are thrown. :param new_host_defaults: If a new host needs to be created, use this defaults. :param new_service_defaults: If a new service needs to be created, use this defaults. """ if config is not None and (config_file is not None and config_file is not False): raise PretiacException("Specify config OR config_file. Not both!") c: Optional[Config] = None if config: c = config elif config_file is False: c = Config() else: c = load_config_file(config_file) if api_endpoint_host is not None: c.api_endpoint_host = api_endpoint_host if api_endpoint_port is not None: c.api_endpoint_port = api_endpoint_port if c.api_endpoint_port is None: c.api_endpoint_port = 5665 if http_basic_username is not None: c.http_basic_username = http_basic_username if http_basic_password is not None: c.http_basic_password = http_basic_password if client_private_key is not None: c.client_private_key = client_private_key if client_certificate is not None: c.client_certificate = client_certificate if ca_certificate is not None: c.ca_certificate = ca_certificate if suppress_exception is not None: c.suppress_exception = suppress_exception if new_host_defaults is not None: c.new_host_defaults = new_host_defaults if new_service_defaults is not None: c.new_service_defaults = new_service_defaults c.check() return c