Browse Source

Merge branch 'main' into records-rfc-test

pull/930/head
Ross McFarland 3 years ago
committed by GitHub
parent
commit
437e3a6ca2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 70 additions and 59 deletions
  1. +3
    -3
      README.md
  2. +2
    -2
      octodns/cmds/args.py
  3. +2
    -4
      octodns/cmds/report.py
  4. +1
    -1
      octodns/processor/acme.py
  5. +1
    -1
      octodns/processor/ownership.py
  6. +1
    -1
      octodns/provider/base.py
  7. +1
    -1
      octodns/provider/plan.py
  8. +2
    -2
      octodns/provider/yaml.py
  9. +24
    -24
      octodns/record/__init__.py
  10. +6
    -8
      octodns/source/axfr.py
  11. +2
    -4
      octodns/source/envvar.py
  12. +2
    -2
      octodns/source/tinydns.py
  13. +9
    -2
      octodns/zone.py
  14. +2
    -2
      tests/helpers.py
  15. +2
    -2
      tests/test_octodns_provider_base.py
  16. +10
    -0
      tests/test_octodns_zone.py

+ 3
- 3
README.md View File

@ -1,4 +1,4 @@
<img src="https://raw.githubusercontent.com/octodns/octodns/master/docs/logos/octodns-logo.png?" alt="OctoDNS Logo" height=251 width=404>
<img src="https://raw.githubusercontent.com/octodns/octodns/main/docs/logos/octodns-logo.png?" alt="OctoDNS Logo" height=251 width=404>
## DNS as code - Tools for managing DNS across multiple providers ## DNS as code - Tools for managing DNS across multiple providers
@ -178,7 +178,7 @@ After the reviews it's time to branch deploy the change.
![Output of a deployment command](/docs/assets/deploy.png) ![Output of a deployment command](/docs/assets/deploy.png)
If that goes smoothly, you again see the expected changes, and verify them with `dig` and/or `octodns-report` you're good to hit the merge button. If there are problems you can quickly do a `.deploy dns/master` to go back to the previous state.
If that goes smoothly, you again see the expected changes, and verify them with `dig` and/or `octodns-report` you're good to hit the merge button. If there are problems you can quickly do a `.deploy dns/main` to go back to the previous state.
### Bootstrapping config files ### Bootstrapping config files
@ -378,7 +378,7 @@ If you know of any other resources, please do let us know!
OctoDNS is licensed under the [MIT license](LICENSE). OctoDNS is licensed under the [MIT license](LICENSE).
The MIT license grant is not for GitHub's trademarks, which include the logo designs. GitHub reserves all trademark and copyright rights in and to all GitHub trademarks. GitHub's logos include, for instance, the stylized designs that include "logo" in the file title in the following folder: https://github.com/octodns/octodns/tree/master/docs/logos/
The MIT license grant is not for GitHub's trademarks, which include the logo designs. GitHub reserves all trademark and copyright rights in and to all GitHub trademarks. GitHub's logos include, for instance, the stylized designs that include "logo" in the file title in the following folder: https://github.com/octodns/octodns/tree/main/docs/logos/
GitHub® and its stylized versions and the Invertocat mark are GitHub's Trademarks or registered Trademarks. When using GitHub's logos, be sure to follow the GitHub logo guidelines. GitHub® and its stylized versions and the Invertocat mark are GitHub's Trademarks or registered Trademarks. When using GitHub's logos, be sure to follow the GitHub logo guidelines.


+ 2
- 2
octodns/cmds/args.py View File

@ -18,7 +18,7 @@ class ArgumentParser(_Base):
''' '''
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ArgumentParser, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
def parse_args(self, default_log_level=INFO): def parse_args(self, default_log_level=INFO):
version = f'octoDNS {__VERSION__}' version = f'octoDNS {__VERSION__}'
@ -50,7 +50,7 @@ class ArgumentParser(_Base):
'--debug', action='store_true', default=False, help=_help '--debug', action='store_true', default=False, help=_help
) )
args = super(ArgumentParser, self).parse_args()
args = super().parse_args()
self._setup_logging(args, default_log_level) self._setup_logging(args, default_log_level)
return args return args


+ 2
- 4
octodns/cmds/report.py View File

@ -16,13 +16,11 @@ from octodns.manager import Manager
class AsyncResolver(Resolver): class AsyncResolver(Resolver):
def __init__(self, num_workers, *args, **kwargs): def __init__(self, num_workers, *args, **kwargs):
super(AsyncResolver, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.executor = ThreadPoolExecutor(max_workers=num_workers) self.executor = ThreadPoolExecutor(max_workers=num_workers)
def query(self, *args, **kwargs): def query(self, *args, **kwargs):
return self.executor.submit(
super(AsyncResolver, self).query, *args, **kwargs
)
return self.executor.submit(super().query, *args, **kwargs)
def main(): def main():


+ 1
- 1
octodns/processor/acme.py View File

@ -25,7 +25,7 @@ class AcmeMangingProcessor(BaseProcessor):
- acme - acme
... ...
''' '''
super(AcmeMangingProcessor, self).__init__(name)
super().__init__(name)
self._owned = set() self._owned = set()


+ 1
- 1
octodns/processor/ownership.py View File

@ -15,7 +15,7 @@ from .base import BaseProcessor
# and thus "own" them going forward. # and thus "own" them going forward.
class OwnershipProcessor(BaseProcessor): class OwnershipProcessor(BaseProcessor):
def __init__(self, name, txt_name='_owner', txt_value='*octodns*'): def __init__(self, name, txt_name='_owner', txt_value='*octodns*'):
super(OwnershipProcessor, self).__init__(name)
super().__init__(name)
self.txt_name = txt_name self.txt_name = txt_name
self.txt_value = txt_value self.txt_value = txt_value
self._txt_values = [txt_value] self._txt_values = [txt_value]


+ 1
- 1
octodns/provider/base.py View File

@ -17,7 +17,7 @@ class BaseProvider(BaseSource):
delete_pcent_threshold=Plan.MAX_SAFE_DELETE_PCENT, delete_pcent_threshold=Plan.MAX_SAFE_DELETE_PCENT,
strict_supports=False, strict_supports=False,
): ):
super(BaseProvider, self).__init__(id)
super().__init__(id)
self.log.debug( self.log.debug(
'__init__: id=%s, apply_disabled=%s, ' '__init__: id=%s, apply_disabled=%s, '
'update_pcent_threshold=%.2f, ' 'update_pcent_threshold=%.2f, '


+ 1
- 1
octodns/provider/plan.py View File

@ -136,7 +136,7 @@ class _PlanOutput(object):
class PlanLogger(_PlanOutput): class PlanLogger(_PlanOutput):
def __init__(self, name, level='info'): def __init__(self, name, level='info'):
super(PlanLogger, self).__init__(name)
super().__init__(name)
try: try:
self.level = { self.level = {
'debug': DEBUG, 'debug': DEBUG,


+ 2
- 2
octodns/provider/yaml.py View File

@ -128,7 +128,7 @@ class YamlProvider(BaseProvider):
enforce_order, enforce_order,
populate_should_replace, populate_should_replace,
) )
super(YamlProvider, self).__init__(id, *args, **kwargs)
super().__init__(id, *args, **kwargs)
self.directory = directory self.directory = directory
self.default_ttl = default_ttl self.default_ttl = default_ttl
self.enforce_order = enforce_order self.enforce_order = enforce_order
@ -311,7 +311,7 @@ class SplitYamlProvider(YamlProvider):
CATCHALL_RECORD_NAMES = ('*', '') CATCHALL_RECORD_NAMES = ('*', '')
def __init__(self, id, directory, extension='.', *args, **kwargs): def __init__(self, id, directory, extension='.', *args, **kwargs):
super(SplitYamlProvider, self).__init__(id, directory, *args, **kwargs)
super().__init__(id, directory, *args, **kwargs)
self.extension = extension self.extension = extension
def _zone_directory(self, zone): def _zone_directory(self, zone):


+ 24
- 24
octodns/record/__init__.py View File

@ -32,7 +32,7 @@ class Create(Change):
CLASS_ORDERING = 1 CLASS_ORDERING = 1
def __init__(self, new): def __init__(self, new):
super(Create, self).__init__(None, new)
super().__init__(None, new)
def __repr__(self, leader=''): def __repr__(self, leader=''):
source = self.new.source.id if self.new.source else '' source = self.new.source.id if self.new.source else ''
@ -58,7 +58,7 @@ class Delete(Change):
CLASS_ORDERING = 0 CLASS_ORDERING = 0
def __init__(self, existing): def __init__(self, existing):
super(Delete, self).__init__(existing, None)
super().__init__(existing, None)
def __repr__(self, leader=''): def __repr__(self, leader=''):
return f'Delete {self.existing}' return f'Delete {self.existing}'
@ -80,7 +80,7 @@ class ValidationError(RecordException):
return f'Invalid record {idna_decode(fqdn)}\n - {reasons}' return f'Invalid record {idna_decode(fqdn)}\n - {reasons}'
def __init__(self, fqdn, reasons): def __init__(self, fqdn, reasons):
super(Exception, self).__init__(self.build_message(fqdn, reasons))
super().__init__(self.build_message(fqdn, reasons))
self.fqdn = fqdn self.fqdn = fqdn
self.reasons = reasons self.reasons = reasons
@ -373,7 +373,7 @@ class GeoValue(EqualityTupleMixin):
class ValuesMixin(object): class ValuesMixin(object):
@classmethod @classmethod
def validate(cls, name, fqdn, data): def validate(cls, name, fqdn, data):
reasons = super(ValuesMixin, cls).validate(name, fqdn, data)
reasons = super().validate(name, fqdn, data)
values = data.get('values', data.get('value', [])) values = data.get('values', data.get('value', []))
@ -390,7 +390,7 @@ class ValuesMixin(object):
return {'ttl': rr.ttl, 'type': rr._type, 'values': values} return {'ttl': rr.ttl, 'type': rr._type, 'values': values}
def __init__(self, zone, name, data, source=None): def __init__(self, zone, name, data, source=None):
super(ValuesMixin, self).__init__(zone, name, data, source=source)
super().__init__(zone, name, data, source=source)
try: try:
values = data['values'] values = data['values']
except KeyError: except KeyError:
@ -400,10 +400,10 @@ class ValuesMixin(object):
def changes(self, other, target): def changes(self, other, target):
if self.values != other.values: if self.values != other.values:
return Update(self, other) return Update(self, other)
return super(ValuesMixin, self).changes(other, target)
return super().changes(other, target)
def _data(self): def _data(self):
ret = super(ValuesMixin, self)._data()
ret = super()._data()
if len(self.values) > 1: if len(self.values) > 1:
values = [getattr(v, 'data', v) for v in self.values if v] values = [getattr(v, 'data', v) for v in self.values if v]
if len(values) > 1: if len(values) > 1:
@ -441,7 +441,7 @@ class _GeoMixin(ValuesMixin):
@classmethod @classmethod
def validate(cls, name, fqdn, data): def validate(cls, name, fqdn, data):
reasons = super(_GeoMixin, cls).validate(name, fqdn, data)
reasons = super().validate(name, fqdn, data)
try: try:
geo = dict(data['geo']) geo = dict(data['geo'])
for code, values in geo.items(): for code, values in geo.items():
@ -452,7 +452,7 @@ class _GeoMixin(ValuesMixin):
return reasons return reasons
def __init__(self, zone, name, data, *args, **kwargs): def __init__(self, zone, name, data, *args, **kwargs):
super(_GeoMixin, self).__init__(zone, name, data, *args, **kwargs)
super().__init__(zone, name, data, *args, **kwargs)
try: try:
self.geo = dict(data['geo']) self.geo = dict(data['geo'])
except KeyError: except KeyError:
@ -461,7 +461,7 @@ class _GeoMixin(ValuesMixin):
self.geo[code] = GeoValue(code, values) self.geo[code] = GeoValue(code, values)
def _data(self): def _data(self):
ret = super(_GeoMixin, self)._data()
ret = super()._data()
if self.geo: if self.geo:
geo = {} geo = {}
for code, value in self.geo.items(): for code, value in self.geo.items():
@ -473,7 +473,7 @@ class _GeoMixin(ValuesMixin):
if target.SUPPORTS_GEO: if target.SUPPORTS_GEO:
if self.geo != other.geo: if self.geo != other.geo:
return Update(self, other) return Update(self, other)
return super(_GeoMixin, self).changes(other, target)
return super().changes(other, target)
def __repr__(self): def __repr__(self):
if self.geo: if self.geo:
@ -482,13 +482,13 @@ class _GeoMixin(ValuesMixin):
f'<{klass} {self._type} {self.ttl}, {self.decoded_fqdn}, ' f'<{klass} {self._type} {self.ttl}, {self.decoded_fqdn}, '
f'{self.values}, {self.geo}>' f'{self.values}, {self.geo}>'
) )
return super(_GeoMixin, self).__repr__()
return super().__repr__()
class ValueMixin(object): class ValueMixin(object):
@classmethod @classmethod
def validate(cls, name, fqdn, data): def validate(cls, name, fqdn, data):
reasons = super(ValueMixin, cls).validate(name, fqdn, data)
reasons = super().validate(name, fqdn, data)
reasons.extend( reasons.extend(
cls._value_type.validate(data.get('value', None), cls._type) cls._value_type.validate(data.get('value', None), cls._type)
) )
@ -505,16 +505,16 @@ class ValueMixin(object):
} }
def __init__(self, zone, name, data, source=None): def __init__(self, zone, name, data, source=None):
super(ValueMixin, self).__init__(zone, name, data, source=source)
super().__init__(zone, name, data, source=source)
self.value = self._value_type.process(data['value']) self.value = self._value_type.process(data['value'])
def changes(self, other, target): def changes(self, other, target):
if self.value != other.value: if self.value != other.value:
return Update(self, other) return Update(self, other)
return super(ValueMixin, self).changes(other, target)
return super().changes(other, target)
def _data(self): def _data(self):
ret = super(ValueMixin, self)._data()
ret = super()._data()
if self.value: if self.value:
ret['value'] = getattr(self.value, 'data', self.value) ret['value'] = getattr(self.value, 'data', self.value)
return ret return ret
@ -640,7 +640,7 @@ class _DynamicMixin(object):
@classmethod @classmethod
def validate(cls, name, fqdn, data): def validate(cls, name, fqdn, data):
reasons = super(_DynamicMixin, cls).validate(name, fqdn, data)
reasons = super().validate(name, fqdn, data)
if 'dynamic' not in data: if 'dynamic' not in data:
return reasons return reasons
@ -799,7 +799,7 @@ class _DynamicMixin(object):
return reasons return reasons
def __init__(self, zone, name, data, *args, **kwargs): def __init__(self, zone, name, data, *args, **kwargs):
super(_DynamicMixin, self).__init__(zone, name, data, *args, **kwargs)
super().__init__(zone, name, data, *args, **kwargs)
self.dynamic = {} self.dynamic = {}
@ -829,7 +829,7 @@ class _DynamicMixin(object):
self.dynamic = _Dynamic(pools, parsed) self.dynamic = _Dynamic(pools, parsed)
def _data(self): def _data(self):
ret = super(_DynamicMixin, self)._data()
ret = super()._data()
if self.dynamic: if self.dynamic:
ret['dynamic'] = self.dynamic._data() ret['dynamic'] = self.dynamic._data()
return ret return ret
@ -838,7 +838,7 @@ class _DynamicMixin(object):
if target.SUPPORTS_DYNAMIC: if target.SUPPORTS_DYNAMIC:
if self.dynamic != other.dynamic: if self.dynamic != other.dynamic:
return Update(self, other) return Update(self, other)
return super(_DynamicMixin, self).changes(other, target)
return super().changes(other, target)
def __repr__(self): def __repr__(self):
# TODO: improve this whole thing, we need multi-line... # TODO: improve this whole thing, we need multi-line...
@ -856,7 +856,7 @@ class _DynamicMixin(object):
f'<{klass} {self._type} {self.ttl}, {self.decoded_fqdn}, ' f'<{klass} {self._type} {self.ttl}, {self.decoded_fqdn}, '
f'{values}, {self.dynamic}>' f'{values}, {self.dynamic}>'
) )
return super(_DynamicMixin, self).__repr__()
return super().__repr__()
class _TargetValue(str): class _TargetValue(str):
@ -984,7 +984,7 @@ class AliasRecord(ValueMixin, Record):
reasons = [] reasons = []
if name != '': if name != '':
reasons.append('non-root ALIAS not allowed') reasons.append('non-root ALIAS not allowed')
reasons.extend(super(AliasRecord, cls).validate(name, fqdn, data))
reasons.extend(super().validate(name, fqdn, data))
return reasons return reasons
@ -1094,7 +1094,7 @@ class CnameRecord(_DynamicMixin, ValueMixin, Record):
reasons = [] reasons = []
if name == '': if name == '':
reasons.append('root CNAME not allowed') reasons.append('root CNAME not allowed')
reasons.extend(super(CnameRecord, cls).validate(name, fqdn, data))
reasons.extend(super().validate(name, fqdn, data))
return reasons return reasons
@ -2136,7 +2136,7 @@ class SrvRecord(ValuesMixin, Record):
reasons = [] reasons = []
if not cls._name_re.match(name): if not cls._name_re.match(name):
reasons.append('invalid name for SRV record') reasons.append('invalid name for SRV record')
reasons.extend(super(SrvRecord, cls).validate(name, fqdn, data))
reasons.extend(super().validate(name, fqdn, data))
return reasons return reasons


+ 6
- 8
octodns/source/axfr.py View File

@ -39,7 +39,7 @@ class AxfrBaseSource(BaseSource):
) )
def __init__(self, id): def __init__(self, id):
super(AxfrBaseSource, self).__init__(id)
super().__init__(id)
def populate(self, zone, target=False, lenient=False): def populate(self, zone, target=False, lenient=False):
self.log.debug( self.log.debug(
@ -65,9 +65,7 @@ class AxfrSourceException(Exception):
class AxfrSourceZoneTransferFailed(AxfrSourceException): class AxfrSourceZoneTransferFailed(AxfrSourceException):
def __init__(self): def __init__(self):
super(AxfrSourceZoneTransferFailed, self).__init__(
'Unable to Perform Zone Transfer'
)
super().__init__('Unable to Perform Zone Transfer')
class AxfrSource(AxfrBaseSource): class AxfrSource(AxfrBaseSource):
@ -83,7 +81,7 @@ class AxfrSource(AxfrBaseSource):
def __init__(self, id, master): def __init__(self, id, master):
self.log = logging.getLogger(f'AxfrSource[{id}]') self.log = logging.getLogger(f'AxfrSource[{id}]')
self.log.debug('__init__: id=%s, master=%s', id, master) self.log.debug('__init__: id=%s, master=%s', id, master)
super(AxfrSource, self).__init__(id)
super().__init__(id)
self.master = master self.master = master
def zone_records(self, zone): def zone_records(self, zone):
@ -111,12 +109,12 @@ class ZoneFileSourceException(Exception):
class ZoneFileSourceNotFound(ZoneFileSourceException): class ZoneFileSourceNotFound(ZoneFileSourceException):
def __init__(self): def __init__(self):
super(ZoneFileSourceNotFound, self).__init__('Zone file not found')
super().__init__('Zone file not found')
class ZoneFileSourceLoadFailure(ZoneFileSourceException): class ZoneFileSourceLoadFailure(ZoneFileSourceException):
def __init__(self, error): def __init__(self, error):
super(ZoneFileSourceLoadFailure, self).__init__(str(error))
super().__init__(str(error))
class ZoneFileSource(AxfrBaseSource): class ZoneFileSource(AxfrBaseSource):
@ -148,7 +146,7 @@ class ZoneFileSource(AxfrBaseSource):
file_extension, file_extension,
check_origin, check_origin,
) )
super(ZoneFileSource, self).__init__(id)
super().__init__(id)
self.directory = directory self.directory = directory
self.file_extension = file_extension self.file_extension = file_extension
self.check_origin = check_origin self.check_origin = check_origin


+ 2
- 4
octodns/source/envvar.py View File

@ -11,9 +11,7 @@ class EnvVarSourceException(Exception):
class EnvironmentVariableNotFoundException(EnvVarSourceException): class EnvironmentVariableNotFoundException(EnvVarSourceException):
def __init__(self, data): def __init__(self, data):
super(EnvironmentVariableNotFoundException, self).__init__(
f'Unknown environment variable {data}'
)
super().__init__(f'Unknown environment variable {data}')
class EnvVarSource(BaseSource): class EnvVarSource(BaseSource):
@ -73,7 +71,7 @@ class EnvVarSource(BaseSource):
name, name,
ttl, ttl,
) )
super(EnvVarSource, self).__init__(id)
super().__init__(id)
self.envvar = variable self.envvar = variable
self.name = name self.name = name
self.ttl = ttl self.ttl = ttl


+ 2
- 2
octodns/source/tinydns.py View File

@ -23,7 +23,7 @@ class TinyDnsBaseSource(BaseSource):
split_re = re.compile(r':+') split_re = re.compile(r':+')
def __init__(self, id, default_ttl=3600): def __init__(self, id, default_ttl=3600):
super(TinyDnsBaseSource, self).__init__(id)
super().__init__(id)
self.default_ttl = default_ttl self.default_ttl = default_ttl
def _data_for_A(self, _type, records): def _data_for_A(self, _type, records):
@ -239,7 +239,7 @@ class TinyDnsFileSource(TinyDnsBaseSource):
directory, directory,
default_ttl, default_ttl,
) )
super(TinyDnsFileSource, self).__init__(id, default_ttl)
super().__init__(id, default_ttl)
self.directory = directory self.directory = directory
self._cache = None self._cache = None


+ 9
- 2
octodns/zone.py View File

@ -41,7 +41,8 @@ class Zone(object):
self._root_ns = None self._root_ns = None
# optional leading . to match empty hostname # optional leading . to match empty hostname
# optional trailing . b/c some sources don't have it on their fqdn # optional trailing . b/c some sources don't have it on their fqdn
self._name_re = re.compile(fr'\.?{name}?$')
self._utf8_name_re = re.compile(fr'\.?{idna_decode(name)}?$')
self._idna_name_re = re.compile(fr'\.?{self.name}?$')
# Copy-on-write semantics support, when `not None` this property will # Copy-on-write semantics support, when `not None` this property will
# point to a location with records for this `Zone`. Once `hydrated` # point to a location with records for this `Zone`. Once `hydrated`
@ -63,7 +64,13 @@ class Zone(object):
return self._root_ns return self._root_ns
def hostname_from_fqdn(self, fqdn): def hostname_from_fqdn(self, fqdn):
return self._name_re.sub('', fqdn)
try:
fqdn.encode('ascii')
# it's non-idna or idna encoded
return self._idna_name_re.sub('', idna_encode(fqdn))
except UnicodeEncodeError:
# it has utf8 chars
return self._utf8_name_re.sub('', fqdn)
def add_record(self, record, replace=False, lenient=False): def add_record(self, record, replace=False, lenient=False):
if self._origin: if self._origin:


+ 2
- 2
tests/helpers.py View File

@ -95,7 +95,7 @@ class TemporaryDirectory(object):
class WantsConfigProcessor(BaseProcessor): class WantsConfigProcessor(BaseProcessor):
def __init__(self, name, some_config): def __init__(self, name, some_config):
super(WantsConfigProcessor, self).__init__(name)
super().__init__(name)
class PlannableProvider(BaseProvider): class PlannableProvider(BaseProvider):
@ -106,7 +106,7 @@ class PlannableProvider(BaseProvider):
SUPPORTS = set(('A', 'AAAA', 'TXT')) SUPPORTS = set(('A', 'AAAA', 'TXT'))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(PlannableProvider, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
def populate(self, zone, source=False, target=False, lenient=False): def populate(self, zone, source=False, target=False, lenient=False):
pass pass


+ 2
- 2
tests/test_octodns_provider_base.py View File

@ -53,7 +53,7 @@ class HelperProvider(BaseProvider):
class TrickyProcessor(BaseProcessor): class TrickyProcessor(BaseProcessor):
def __init__(self, name, add_during_process_target_zone): def __init__(self, name, add_during_process_target_zone):
super(TrickyProcessor, self).__init__(name)
super().__init__(name)
self.add_during_process_target_zone = add_during_process_target_zone self.add_during_process_target_zone = add_during_process_target_zone
self.reset() self.reset()
@ -640,7 +640,7 @@ class TestBaseProvider(TestCase):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.log = MagicMock() self.log = MagicMock()
super(MinimalProvider, self).__init__('minimal', **kwargs)
super().__init__('minimal', **kwargs)
normal = MinimalProvider(strict_supports=False) normal = MinimalProvider(strict_supports=False)
# Should log and not expect # Should log and not expect


+ 10
- 0
tests/test_octodns_zone.py View File

@ -47,10 +47,16 @@ class TestZone(TestCase):
('foo.bar', 'foo.bar.unit.tests'), ('foo.bar', 'foo.bar.unit.tests'),
('foo.unit.tests', 'foo.unit.tests.unit.tests.'), ('foo.unit.tests', 'foo.unit.tests.unit.tests.'),
('foo.unit.tests', 'foo.unit.tests.unit.tests'), ('foo.unit.tests', 'foo.unit.tests.unit.tests'),
# if we pass utf8 we get utf8
('déjà', 'déjà.unit.tests'), ('déjà', 'déjà.unit.tests'),
('déjà.foo', 'déjà.foo.unit.tests'), ('déjà.foo', 'déjà.foo.unit.tests'),
('bar.déjà', 'bar.déjà.unit.tests'), ('bar.déjà', 'bar.déjà.unit.tests'),
('bar.déjà.foo', 'bar.déjà.foo.unit.tests'), ('bar.déjà.foo', 'bar.déjà.foo.unit.tests'),
# if we pass idna we get idna
('xn--dj-kia8a', 'xn--dj-kia8a.unit.tests'),
('xn--dj-kia8a.foo', 'xn--dj-kia8a.foo.unit.tests'),
('bar.xn--dj-kia8a', 'bar.xn--dj-kia8a.unit.tests'),
('bar.xn--dj-kia8a.foo', 'bar.xn--dj-kia8a.foo.unit.tests'),
): ):
self.assertEqual(hostname, zone.hostname_from_fqdn(fqdn)) self.assertEqual(hostname, zone.hostname_from_fqdn(fqdn))
@ -68,6 +74,10 @@ class TestZone(TestCase):
('déjà.foo', 'déjà.foo.grüßen.de'), ('déjà.foo', 'déjà.foo.grüßen.de'),
('bar.déjà', 'bar.déjà.grüßen.de'), ('bar.déjà', 'bar.déjà.grüßen.de'),
('bar.déjà.foo', 'bar.déjà.foo.grüßen.de'), ('bar.déjà.foo', 'bar.déjà.foo.grüßen.de'),
('xn--dj-kia8a', 'xn--dj-kia8a.xn--gren-wna7o.de'),
('xn--dj-kia8a.foo', 'xn--dj-kia8a.foo.xn--gren-wna7o.de'),
('bar.xn--dj-kia8a', 'bar.xn--dj-kia8a.xn--gren-wna7o.de'),
('bar.xn--dj-kia8a.foo', 'bar.xn--dj-kia8a.foo.xn--gren-wna7o.de'),
): ):
self.assertEqual(hostname, zone.hostname_from_fqdn(fqdn)) self.assertEqual(hostname, zone.hostname_from_fqdn(fqdn))


Loading…
Cancel
Save