Support adding HE DNS entries
continuous-integration/drone the build failed Details

This commit is contained in:
Olivier 'reivilibre' 2022-03-17 23:18:33 +00:00
parent 6e16ac7ec6
commit 7360e0d614
1 changed files with 86 additions and 4 deletions

View File

@ -14,6 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with Scone. If not, see <https://www.gnu.org/licenses/>.
import logging
from asyncio import Lock
from typing import Any, Dict, List, Optional, Tuple, Union
@ -25,14 +26,62 @@ from scone.head.kitchen import Kitchen, Preparation
from scone.head.recipe import HeadRecipe, RecipeContext
from scone.head.utils import check_type
logger = logging.getLogger(__name__)
@attr.s(auto_attribs=True)
class DnsRecord:
pass
subdomain: str
kind: str
value: str
ttl: Optional[str]
priority: Optional[str]
def parse_records(given: Union[Any, Dict[str, Any]]) -> List[DnsRecord]:
pass
def parse_records(given_raw: Union[Any, Dict[str, Dict[str, str]]]) -> List[DnsRecord]:
given = check_type(given_raw, dict, "records")
the_list: List[DnsRecord] = []
for key, attributes in given.items():
# keys: "xyz A"
# values: dicts, with keys:
# - v: 1.2.3.4
# - ttl: 86400
# - priority: 50 (for MXes)
pieces = key.split(" ")
if len(pieces) > 2:
raise ValueError(
f"Key {key} should be space-separable with 2 or less pieces."
)
if len(pieces) == 2:
subdomain, kind = pieces
else:
assert len(pieces) == 1
(kind,) = pieces
subdomain = ""
ttl_raw = attributes.get("ttl")
prio_raw = attributes.get("priority")
record_value = attributes.get("v", attributes.get("value", None))
if record_value is None:
raise ValueError("No record value")
the_list.append(
DnsRecord(
subdomain=subdomain,
kind=kind,
value=record_value,
ttl=None if ttl_raw is None else str(ttl_raw),
priority=None if prio_raw is None else str(prio_raw),
)
)
return the_list
@attr.s(auto_attribs=True)
@ -117,10 +166,43 @@ class HurricaneElectricDns(HeadRecipe):
return domain.records
async def cook(self, kitchen: Kitchen) -> None:
# TODO(correctness): can't handle multiple DNS records
# with same (type, subdomain)
kitchen.get_dependency_tracker().ignore()
cached = await self._get_client(kitchen.head)
records = await self._get_records(cached, cached.domains[self.domain])
records_cache: Dict[Tuple[str, str], HeRecord] = {}
for record in records:
print(record)
dotted_subdomain_suffix = f".{self.domain}"
if record.host == self.domain:
subdomain = ""
elif record.host.endswith(dotted_subdomain_suffix):
subdomain = record.host[: -len(dotted_subdomain_suffix)]
else:
raise ValueError(f"Can't figure out subdomain for {record.host}")
records_cache[(subdomain, record.type)] = record
logger.debug("Present records: %r", records_cache.keys())
for wanted_record in self.records:
wr_key = (wanted_record.subdomain, wanted_record.kind)
logger.debug("Want %r: %r", wr_key, wanted_record)
existing_record = records_cache.get(wr_key)
if existing_record is not None:
# TODO(correctness): amend as needed
logger.debug("Found existing %r", existing_record)
else:
logger.debug("Will need to create new one")
async with cached.lock:
cached.client.add_record(
self.domain,
wanted_record.subdomain,
wanted_record.kind,
wanted_record.value,
wanted_record.priority or None,
wanted_record.ttl or 86400,
)