mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
add outgoing http webhook for queries
This commit is contained in:
@@ -9,7 +9,6 @@ from pathlib import Path
|
||||
|
||||
# Third Party
|
||||
import yaml
|
||||
from aiofile import AIOFile
|
||||
from pydantic import ValidationError
|
||||
|
||||
# Project
|
||||
@@ -19,7 +18,7 @@ from hyperglass.log import (
|
||||
enable_file_logging,
|
||||
enable_syslog_logging,
|
||||
)
|
||||
from hyperglass.util import check_path, set_app_path
|
||||
from hyperglass.util import check_path, set_app_path, set_cache_env
|
||||
from hyperglass.constants import (
|
||||
CREDIT,
|
||||
DEFAULT_HELP,
|
||||
@@ -115,57 +114,6 @@ def _config_optional(config_path: Path) -> dict:
|
||||
return config
|
||||
|
||||
|
||||
async def _config_main():
|
||||
"""Open main config file and load YAML to dict.
|
||||
|
||||
Returns:
|
||||
{dict} -- Main config file
|
||||
"""
|
||||
config = {}
|
||||
try:
|
||||
async with AIOFile(CONFIG_MAIN, "r") as cf:
|
||||
raw = await cf.read()
|
||||
config = yaml.safe_load(raw) or {}
|
||||
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
|
||||
raise ConfigError(error_msg=str(yaml_error)) from None
|
||||
return config
|
||||
|
||||
|
||||
async def _config_commands():
|
||||
"""Open commands config file and load YAML to dict.
|
||||
|
||||
Returns:
|
||||
{dict} -- Commands config file
|
||||
"""
|
||||
if CONFIG_COMMANDS is None:
|
||||
config = {}
|
||||
else:
|
||||
try:
|
||||
async with AIOFile(CONFIG_COMMANDS, "r") as cf:
|
||||
raw = await cf.read()
|
||||
config = yaml.safe_load(raw) or {}
|
||||
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
|
||||
raise ConfigError(error_msg=str(yaml_error)) from None
|
||||
log.debug("Unvalidated commands: {c}", c=config)
|
||||
return config
|
||||
|
||||
|
||||
async def _config_devices():
|
||||
"""Open devices config file and load YAML to dict.
|
||||
|
||||
Returns:
|
||||
{dict} -- Devices config file
|
||||
"""
|
||||
try:
|
||||
async with AIOFile(CONFIG_DEVICES, "r") as cf:
|
||||
raw = await cf.read()
|
||||
config = yaml.safe_load(raw)
|
||||
log.debug("Unvalidated device config: {c}", c=config)
|
||||
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
|
||||
raise ConfigError(error_msg=str(yaml_error)) from None
|
||||
return config
|
||||
|
||||
|
||||
user_config = _config_optional(CONFIG_MAIN)
|
||||
|
||||
# Read raw debug value from config to enable debugging quickly.
|
||||
@@ -188,6 +136,8 @@ except ValidationError as validation_errors:
|
||||
error_msg=error["msg"],
|
||||
)
|
||||
|
||||
set_cache_env(db=params.cache.database, host=params.cache.host, port=params.cache.port)
|
||||
|
||||
# Re-evaluate debug state after config is validated
|
||||
set_log_level(logger=log, debug=params.debug)
|
||||
|
||||
|
@@ -1,14 +1,28 @@
|
||||
"""Validate logging configuration."""
|
||||
|
||||
# Standard Library
|
||||
from typing import Optional
|
||||
import base64
|
||||
from ast import literal_eval
|
||||
from typing import Dict, Union, Optional
|
||||
from pathlib import Path
|
||||
|
||||
# Third Party
|
||||
from pydantic import ByteSize, StrictInt, StrictStr, StrictBool, DirectoryPath, constr
|
||||
from pydantic import (
|
||||
ByteSize,
|
||||
SecretStr,
|
||||
StrictInt,
|
||||
StrictStr,
|
||||
AnyHttpUrl,
|
||||
StrictBool,
|
||||
StrictFloat,
|
||||
DirectoryPath,
|
||||
constr,
|
||||
validator,
|
||||
)
|
||||
|
||||
# Project
|
||||
from hyperglass.configuration.models._utils import HyperglassModel
|
||||
from hyperglass.constants import __version__
|
||||
from hyperglass.configuration.models._utils import HyperglassModel, HyperglassModelExtra
|
||||
|
||||
|
||||
class Syslog(HyperglassModel):
|
||||
@@ -19,10 +33,70 @@ class Syslog(HyperglassModel):
|
||||
port: StrictInt = 514
|
||||
|
||||
|
||||
class HttpAuth(HyperglassModel):
|
||||
"""HTTP hook authentication parameters."""
|
||||
|
||||
mode: constr(regex=r"(basic|api_key)") = "basic"
|
||||
username: Optional[StrictStr]
|
||||
password: SecretStr
|
||||
|
||||
def api_key(self, header_name="X-API-Key"):
|
||||
"""Represent authentication as an API key header."""
|
||||
return {header_name: self.password.get_secret_value()}
|
||||
|
||||
def basic(self):
|
||||
"""Represent HTTP basic authentication."""
|
||||
return (self.username, self.password.get_secret_value())
|
||||
|
||||
|
||||
class Http(HyperglassModelExtra):
|
||||
"""HTTP logging parameters."""
|
||||
|
||||
enable: StrictBool = True
|
||||
host: AnyHttpUrl
|
||||
authentication: Optional[HttpAuth]
|
||||
headers: Dict[StrictStr, Union[StrictStr, StrictInt, StrictBool, None]] = {}
|
||||
params: Dict[StrictStr, Union[StrictStr, StrictInt, StrictBool, None]] = {}
|
||||
verify_ssl: StrictBool = True
|
||||
timeout: Union[StrictFloat, StrictInt] = 5.0
|
||||
|
||||
@validator("headers", "params")
|
||||
def stringify_headers_params(cls, value):
|
||||
"""Ensure headers and URL parameters are strings."""
|
||||
for k, v in value.items():
|
||||
if not isinstance(v, str):
|
||||
value[k] = str(v)
|
||||
return value
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Initialize model, add obfuscated connection details as attribute."""
|
||||
super().__init__(**kwargs)
|
||||
dumped = {
|
||||
"headers": self.headers,
|
||||
"params": self.params,
|
||||
"verify": self.verify_ssl,
|
||||
"timeout": self.timeout,
|
||||
}
|
||||
dumped["headers"].update({"user-agent": f"hyperglass/{__version__}"})
|
||||
|
||||
if self.authentication is not None:
|
||||
if self.authentication.mode == "api_key":
|
||||
dumped["headers"].update(self.authentication.api_key())
|
||||
else:
|
||||
dumped["auth"] = self.authentication.basic()
|
||||
|
||||
self._obscured_params = base64.encodestring(str(dumped).encode())
|
||||
|
||||
def decoded(self):
|
||||
"""Decode connection details."""
|
||||
return literal_eval(base64.decodestring(self._obscured_params).decode())
|
||||
|
||||
|
||||
class Logging(HyperglassModel):
|
||||
"""Validation model for logging configuration."""
|
||||
|
||||
directory: DirectoryPath = Path("/tmp") # noqa: S108
|
||||
format: constr(regex=r"(text|json)") = "text"
|
||||
syslog: Optional[Syslog]
|
||||
max_size: ByteSize = "50MB"
|
||||
syslog: Optional[Syslog]
|
||||
http: Optional[Http]
|
||||
|
Reference in New Issue
Block a user