You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

77 lines
2.6 KiB

#
#
#
from logging import getLogger
from octodns.record import Record
from octodns.source.base import BaseSource
# Based on https://stackoverflow.com/a/3954407
def _fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
class FibonacciProvider(BaseSource):
# Here only TXT records are supported
SUPPORTS = ('TXT',)
# Do-not support (deprecated) GEO records
SUPPORTS_GEO = False
# This is pretty much boilerplate, create a logger with a standard name,
# call up to the parent class BaseSource's __init__, store our
# attributes, and then calculate our fibonacci sequence
def __init__(self, id, n, ttl=3600):
klass = self.__class__.__name__
self.log = getLogger(f'{klass}[{id}]')
self.log.debug(
'__init__: id=%s, variable=%s, name=%s, ttl=%d', id, n, ttl
)
super().__init__(id)
self.n = n
self.ttl = ttl
# calculate the requested number of values
self.values = list(_fibonacci(n))
def populate(self, zone, target=False, lenient=False):
# This is the method adding records to the zone. For a source it's the
# only thing that needs to be implemented. Again there's some best
# practices wrapping our custom logic, mostly for logging/debug
# purposes.
self.log.debug(
'populate: name=%s, target=%s, lenient=%s',
zone.name,
target,
lenient,
)
before = len(zone.records)
# This is where the logic of the source lives. Here it's simply
# translated the previously calculated fibonacci sequence into
# corresponding TXT records. It could be anything: reading data from
# disk, calling APIs, ...
for i, value in enumerate(self.values):
# If there's a chance the generated record may result in validation
# errors it would make sense to pass lenient to new
txt = Record.new(
zone,
f'fibonacci-{i}',
{'value': str(value), 'ttl': self.ttl, 'type': 'TXT'},
)
# lenient should always be passed to add_record. If there's a
# chance the source will create records that conflict with
# something previously added by another provider it may make sense
# to include `replace` here, possibly with an additional provider
# parameter `populate_should_replace`
zone.add_record(txt, lenient=lenient)
self.log.info(
'populate: found %s records, exists=False',
len(zone.records) - before,
)