From fe1077bfce6cee0742a919f20fad6df9eb0ef785 Mon Sep 17 00:00:00 2001 From: Michael Hinz Date: Tue, 29 Apr 2025 16:35:52 +0200 Subject: [PATCH] start writing my own API wrapper --- pdnsapi/README.md | 5 +++++ pdnsapi/__init__.py | 29 +++++++++++++++++++++++++++++ testapi.py | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 pdnsapi/README.md create mode 100644 pdnsapi/__init__.py create mode 100644 testapi.py diff --git a/pdnsapi/README.md b/pdnsapi/README.md new file mode 100644 index 0000000..968ac9e --- /dev/null +++ b/pdnsapi/README.md @@ -0,0 +1,5 @@ +# PowerDNS API wrapper library + +Following [this tutorial](https://www.pretzellogix.net/2021/12/08/how-to-write-a-python3-sdk-library-module-for-a-json-rest-api/) + +Michael Hinz, 2025-04-29 diff --git a/pdnsapi/__init__.py b/pdnsapi/__init__.py new file mode 100644 index 0000000..07fc454 --- /dev/null +++ b/pdnsapi/__init__.py @@ -0,0 +1,29 @@ +import requests +import requests.packages +from typing import List, Dict + + +class PdnsRestAdapter: + def __init__(self, hostname: str, api_key: str = '', ver: str = 'v1'): + self.url = f"http://{hostname}/api/{ver}/" + self._api_key = api_key + + def get(self, endpoint: str) -> List[Dict]: + full_url = self.url + endpoint + headers = {'X-API-key': self._api_key} + response = requests.get(url=full_url, headers=headers) + data_out = response.json() + return data_out + if response.status.code >= 200 and response.status.code <= 299: + return data_out + raise Exception(data_out['message']) # TODO: raise custom exception later + + def post(self, endpoint: str, params: Dict = None, data: Dict = None): + full_url = self.url + endpoint + headers = {'X-API-key': self._api_key} + response = requests.post(url=full_url, params=params, headers=headers, json=data) + data_out = response.json() + return data_out + if response.status.code >= 200 and response.status.code <= 299: + return + raise Exception(data_out['message']) # TODO: raise custom exception later diff --git a/testapi.py b/testapi.py new file mode 100644 index 0000000..33afe4b --- /dev/null +++ b/testapi.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +# import requests # unused for now +from pdnsapi import PdnsRestAdapter + +api = PdnsRestAdapter('localhost:8081/', 'pdns-supersecret') +output = api.get('servers/localhost/zones/test1.nhn.no') + +print(f"{output}") + +# NOTE: doesn't work yet. Maybe wrong arguments? +# api.post('servers/localhost/zones/test1.nhn.no/test.txt', {'type': 'A'}, {'type': 'A'}) + +# copy of error message: +# Traceback (most recent call last): +# File "/home/michael/projects/pdns_dnssec/.venv/lib/python3.12/site-packages/requests/models.py", line 974, in json +# return complexjson.loads(self.text, **kwargs) +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# File "/home/michael/.local/share/uv/python/cpython-3.12.9-linux-x86_64-gnu/lib/python3.12/json/__init__.py", line 346, in loads +# return _default_decoder.decode(s) +# ^^^^^^^^^^^^^^^^^^^^^^^^^^ +# File "/home/michael/.local/share/uv/python/cpython-3.12.9-linux-x86_64-gnu/lib/python3.12/json/decoder.py", line 338, in decode +# obj, end = self.raw_decode(s, idx=_w(s, 0).end()) +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# File "/home/michael/.local/share/uv/python/cpython-3.12.9-linux-x86_64-gnu/lib/python3.12/json/decoder.py", line 356, in raw_decode +# raise JSONDecodeError("Expecting value", s, err.value) from None +# json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) +# +# During handling of the above exception, another exception occurred: +# +# Traceback (most recent call last): +# File "/home/michael/projects/pdns_dnssec/testapi.py", line 11, in +# api.post('servers/localhost/zones/test1.nhn.no/test.txt', {'type': 'A'}, {'type': 'A'}) +# File "/home/michael/projects/pdns_dnssec/pdnsapi/__init__.py", line 25, in post +# data_out = response.json() +# ^^^^^^^^^^^^^^^ +# File "/home/michael/projects/pdns_dnssec/.venv/lib/python3.12/site-packages/requests/models.py", line 978, in json +# raise RequestsJSONDecodeError(e.msg, e.doc, e.pos) +# requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)