refactor: improve exception handling
- clear exception context - use TypeError instead of asserts
This commit is contained in:
parent
5564a44d0d
commit
1eb51184e5
4 changed files with 34 additions and 23 deletions
|
@ -1,8 +1,8 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from typing import Any, Optional
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import tomllib
|
import tomllib
|
||||||
|
|
||||||
|
@ -40,15 +40,30 @@ def config_parse_dict(raw_conf: dict[str, Any], key: str) -> dict[str, str]:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
for k, v in raw_conf[key].items():
|
for k, v in raw_conf[key].items():
|
||||||
assert isinstance(k, str), f'"{k}" is not a string'
|
if not isinstance(k, str):
|
||||||
assert isinstance(v, str), f'"{k}" value "{v}" is not a string'
|
raise TypeError(f'"{k}" is not a string')
|
||||||
|
if not isinstance(v, str):
|
||||||
|
raise TypeError(f'"{k}" value "{v}" is not a string')
|
||||||
|
|
||||||
result: dict[str, str] = raw_conf[key]
|
result: dict[str, str] = raw_conf[key]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def config_parse_list(raw_conf: dict[str, Any], key: str) -> list[str]:
|
||||||
|
result: list[str] = []
|
||||||
|
|
||||||
def read_config(path: Optional[str]) -> Config:
|
if not isinstance(raw_conf[key], list):
|
||||||
|
raise TypeError(f'"{key}" must be a list, not {type(raw_conf[key]).__name__}')
|
||||||
|
|
||||||
|
for item in raw_conf[key]:
|
||||||
|
if not isinstance(item, str):
|
||||||
|
raise TypeError(f'"{key}" list item must be a string')
|
||||||
|
result.append(item)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def read_config(path: str | None) -> Config:
|
||||||
if not path:
|
if not path:
|
||||||
# should be here only when running from hook
|
# should be here only when running from hook
|
||||||
path = os.getenv('NYACME_CONFIG', '/etc/nyacme.toml')
|
path = os.getenv('NYACME_CONFIG', '/etc/nyacme.toml')
|
||||||
|
@ -67,10 +82,7 @@ def read_config(path: Optional[str]) -> Config:
|
||||||
|
|
||||||
post_acquire = []
|
post_acquire = []
|
||||||
if 'post_acquire' in raw_conf:
|
if 'post_acquire' in raw_conf:
|
||||||
assert isinstance(raw_conf['post_acquire'], list), 'post_acquire is not a list'
|
post_acquire = config_parse_list(raw_conf, 'post_acquire')
|
||||||
for cmd in raw_conf['post_acquire']:
|
|
||||||
assert isinstance(cmd, str), 'post_acquire item has to be a string'
|
|
||||||
post_acquire.append(cmd)
|
|
||||||
|
|
||||||
c.post_acquire = post_acquire
|
c.post_acquire = post_acquire
|
||||||
|
|
||||||
|
@ -83,9 +95,6 @@ def read_config(path: Optional[str]) -> Config:
|
||||||
log.error('missing "certificates"')
|
log.error('missing "certificates"')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
c.certificates = []
|
c.certificates = config_parse_list(raw_conf, 'certificates')
|
||||||
for cert in raw_conf['certificates']:
|
|
||||||
assert isinstance(cert, str), 'certificate should be a string'
|
|
||||||
c.certificates.append(cert)
|
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|
|
@ -29,7 +29,7 @@ class HEHandler(Handler):
|
||||||
except urllib.error.HTTPError as ex:
|
except urllib.error.HTTPError as ex:
|
||||||
self.log.error('cannot set the record %s: %s', record_name, ex)
|
self.log.error('cannot set the record %s: %s', record_name, ex)
|
||||||
res = ex.fp.read().decode('utf-8')
|
res = ex.fp.read().decode('utf-8')
|
||||||
raise Exception(res)
|
raise Exception(res) from ex
|
||||||
|
|
||||||
def create(self, record_name: str, record_value: str) -> None:
|
def create(self, record_name: str, record_value: str) -> None:
|
||||||
self.log.info('creating %s with value %s', record_name, record_value)
|
self.log.info('creating %s with value %s', record_name, record_value)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import json
|
import json
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from typing import Any, Optional
|
from typing import Any
|
||||||
|
|
||||||
from ..config import Config
|
from ..config import Config
|
||||||
from .base import Handler
|
from .base import Handler
|
||||||
|
@ -22,7 +22,7 @@ class HetznerHandler(Handler):
|
||||||
self.nameservers = zone['ns']
|
self.nameservers = zone['ns']
|
||||||
break
|
break
|
||||||
|
|
||||||
def fetch(self, url: str, data: Optional[Any] = None, **kwargs: str) -> Any:
|
def fetch(self, url: str, data: Any | None = None, **kwargs: str) -> Any:
|
||||||
req = urllib.request.Request('https://dns.hetzner.com/api/v1' + url)
|
req = urllib.request.Request('https://dns.hetzner.com/api/v1' + url)
|
||||||
req.add_header('Auth-API-Token', self.secret)
|
req.add_header('Auth-API-Token', self.secret)
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
|
@ -39,9 +39,9 @@ class HetznerHandler(Handler):
|
||||||
self.log.error('cannot %s %s: %s', req.method, url, ex)
|
self.log.error('cannot %s %s: %s', req.method, url, ex)
|
||||||
res = ex.fp.read().decode('utf-8')
|
res = ex.fp.read().decode('utf-8')
|
||||||
try:
|
try:
|
||||||
raise Exception(json.loads(res)['error'])
|
raise Exception(json.loads(res)['error']) from None
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
raise Exception(res)
|
raise Exception(res) from None
|
||||||
|
|
||||||
def create(self, record_name: str, record_value: str) -> None:
|
def create(self, record_name: str, record_value: str) -> None:
|
||||||
self.remove(record_name)
|
self.remove(record_name)
|
||||||
|
|
|
@ -17,9 +17,11 @@ class PorkbunHandler(Handler):
|
||||||
|
|
||||||
self.nameservers = self.fetch(f'/domain/getNs/{self.zone}')['ns']
|
self.nameservers = self.fetch(f'/domain/getNs/{self.zone}')['ns']
|
||||||
|
|
||||||
def fetch(self, url: str, data: dict[str, Any] = {}) -> Any:
|
def fetch(self, url: str, data: dict[str, Any] | None = None) -> Any:
|
||||||
req = urllib.request.Request('https://api.porkbun.com/api/json/v3' + url)
|
req = urllib.request.Request('https://api.porkbun.com/api/json/v3' + url)
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
data['apikey'] = self.apikey
|
data['apikey'] = self.apikey
|
||||||
data['secretapikey'] = self.secretapikey
|
data['secretapikey'] = self.secretapikey
|
||||||
req.data = json.dumps(data).encode('utf-8')
|
req.data = json.dumps(data).encode('utf-8')
|
||||||
|
@ -27,17 +29,17 @@ class PorkbunHandler(Handler):
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
try:
|
try:
|
||||||
with urllib.request.urlopen(req) as f:
|
with urllib.request.urlopen(req) as f:
|
||||||
data = json.load(f)
|
res = json.load(f)
|
||||||
if data['status'] != 'SUCCESS':
|
if res['status'] != 'SUCCESS':
|
||||||
raise Exception(data['message'])
|
raise Exception(res['message'])
|
||||||
return data
|
return res
|
||||||
except urllib.error.HTTPError as ex:
|
except urllib.error.HTTPError as ex:
|
||||||
self.log.error('cannot %s %s: %s', req.method, url, ex)
|
self.log.error('cannot %s %s: %s', req.method, url, ex)
|
||||||
res = ex.fp.read().decode('utf-8')
|
res = ex.fp.read().decode('utf-8')
|
||||||
try:
|
try:
|
||||||
raise Exception(json.loads(res)['message'])
|
raise Exception(json.loads(res)['message'])
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
raise Exception(res)
|
raise Exception(res) from None
|
||||||
|
|
||||||
def create(self, record_name: str, record_value: str) -> None:
|
def create(self, record_name: str, record_value: str) -> None:
|
||||||
self.remove(record_name)
|
self.remove(record_name)
|
||||||
|
|
Loading…
Reference in a new issue