diff --git a/octodns/record/ip.py b/octodns/record/ip.py index 8ce605b..ab838af 100644 --- a/octodns/record/ip.py +++ b/octodns/record/ip.py @@ -46,9 +46,7 @@ class _IpValue(str): return self def template(self, params): - if '{' not in self: - return self - return self.__class__(self.format(**params)) + return self _IpAddress = _IpValue diff --git a/octodns/record/sshfp.py b/octodns/record/sshfp.py index 4665aa8..e186744 100644 --- a/octodns/record/sshfp.py +++ b/octodns/record/sshfp.py @@ -106,7 +106,7 @@ class SshfpValue(EqualityTupleMixin, dict): return f'{self.algorithm} {self.fingerprint_type} {self.fingerprint}' def template(self, params): - if '{' in self.fingerprint: + if '{' not in self.fingerprint: return self new = self.__class__(self) new.fingerprint = new.fingerprint.format(**params) diff --git a/octodns/record/tlsa.py b/octodns/record/tlsa.py index 904afc8..c6e72e9 100644 --- a/octodns/record/tlsa.py +++ b/octodns/record/tlsa.py @@ -137,7 +137,7 @@ class TlsaValue(EqualityTupleMixin, dict): return f'{self.certificate_usage} {self.selector} {self.matching_type} {self.certificate_association_data}' def template(self, params): - if '{' in self.certificate_association_data: + if '{' not in self.certificate_association_data: return self new = self.__class__(self) new.certificate_association_data = ( diff --git a/tests/test_octodns_record_caa.py b/tests/test_octodns_record_caa.py index 8caecb9..224dd00 100644 --- a/tests/test_octodns_record_caa.py +++ b/tests/test_octodns_record_caa.py @@ -285,3 +285,20 @@ class TestRecordCaa(TestCase): {'type': 'CAA', 'ttl': 600, 'value': {'tag': 'iodef'}}, ) self.assertEqual(['missing value'], ctx.exception.reasons) + + +class TestCaaValue(TestCase): + + def test_template(self): + value = CaaValue( + {'flags': 0, 'tag': 'issue', 'value': 'ca.example.net'} + ) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = CaaValue( + {'flags': 0, 'tag': 'issue', 'value': 'ca.{needle}.net'} + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('ca.42.net', got.value) diff --git a/tests/test_octodns_record_chunked.py b/tests/test_octodns_record_chunked.py index 4d7bbc0..38b8f0e 100644 --- a/tests/test_octodns_record_chunked.py +++ b/tests/test_octodns_record_chunked.py @@ -115,3 +115,15 @@ class TestChunkedValue(TestCase): sc = self.SmallerChunkedMixin(['0123456789']) self.assertEqual(['"01234567" "89"'], sc.chunked_values) + + def test_template(self): + s = 'this.has.no.templating.' + value = _ChunkedValue(s) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + s = 'this.does.{needle}.have.templating.' + value = _ChunkedValue(s) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('this.does.42.have.templating.', got) diff --git a/tests/test_octodns_record_ds.py b/tests/test_octodns_record_ds.py index f0429de..83fea42 100644 --- a/tests/test_octodns_record_ds.py +++ b/tests/test_octodns_record_ds.py @@ -259,3 +259,30 @@ class TestRecordDs(TestCase): self.assertEqual(DsValue(values[1]), a.values[1].data) self.assertEqual('1 2 3 99148c44', a.values[1].rdata_text) self.assertEqual('1 2 3 99148c44', a.values[1].__repr__()) + + +class TestDsValue(TestCase): + + def test_template(self): + value = DsValue( + { + 'key_tag': 0, + 'algorithm': 1, + 'digest_type': 2, + 'digest': 'abcdef0123456', + } + ) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = DsValue( + { + 'key_tag': 0, + 'algorithm': 1, + 'digest_type': 2, + 'digest': 'abcd{needle}ef0123456', + } + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('abcd42ef0123456', got.digest) diff --git a/tests/test_octodns_record_ip.py b/tests/test_octodns_record_ip.py index f9ba62d..818bca1 100644 --- a/tests/test_octodns_record_ip.py +++ b/tests/test_octodns_record_ip.py @@ -27,3 +27,11 @@ class TestRecordIp(TestCase): zone = Zone('unit.tests.', []) a = ARecord(zone, 'a', {'ttl': 42, 'value': '1.2.3.4'}) self.assertEqual('1.2.3.4', a.values[0].rdata_text) + + +class TestIpValue(TestCase): + + def test_template(self): + value = Ipv4Value('1.2.3.4') + # template is a noop + self.assertIs(value, value.template({'needle': 42})) diff --git a/tests/test_octodns_record_loc.py b/tests/test_octodns_record_loc.py index 278b816..80c9505 100644 --- a/tests/test_octodns_record_loc.py +++ b/tests/test_octodns_record_loc.py @@ -715,3 +715,26 @@ class TestRecordLoc(TestCase): self.assertEqual( ['invalid value for size "99999999.99"'], ctx.exception.reasons ) + + +class TestLocValue(TestCase): + + def test_template(self): + value = LocValue( + { + 'lat_degrees': 31, + 'lat_minutes': 58, + 'lat_seconds': 52.1, + 'lat_direction': 'S', + 'long_degrees': 115, + 'long_minutes': 49, + 'long_seconds': 11.7, + 'long_direction': 'E', + 'altitude': 20, + 'size': 10, + 'precision_horz': 10, + 'precision_vert': 2, + } + ) + # loc value template is a noop + self.assertIs(value, value.template({})) diff --git a/tests/test_octodns_record_mx.py b/tests/test_octodns_record_mx.py index a2fba19..57386c4 100644 --- a/tests/test_octodns_record_mx.py +++ b/tests/test_octodns_record_mx.py @@ -268,3 +268,16 @@ class TestRecordMx(TestCase): }, ) self.assertEqual('.', record.values[0].exchange) + + +class TestMxValue(TestCase): + + def test_template(self): + value = MxValue({'preference': 10, 'exchange': 'smtp1.'}) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = MxValue({'preference': 10, 'exchange': 'smtp1.{needle}.'}) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('smtp1.42.', got.exchange) diff --git a/tests/test_octodns_record_naptr.py b/tests/test_octodns_record_naptr.py index b099de4..3c05550 100644 --- a/tests/test_octodns_record_naptr.py +++ b/tests/test_octodns_record_naptr.py @@ -449,3 +449,36 @@ class TestRecordNaptr(TestCase): with self.assertRaises(ValidationError) as ctx: Record.new(self.zone, '', {'type': 'NAPTR', 'ttl': 600, 'value': v}) self.assertEqual(['unrecognized flags "X"'], ctx.exception.reasons) + + +class TestNaptrValue(TestCase): + + def test_template(self): + value = NaptrValue( + { + 'order': 10, + 'preference': 11, + 'flags': 'X', + 'service': 'Y', + 'regexp': 'Z', + 'replacement': '.', + } + ) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = NaptrValue( + { + 'order': 10, + 'preference': 11, + 'flags': 'X', + 'service': 'Y{needle}', + 'regexp': 'Z{needle}', + 'replacement': '.{needle}', + } + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('Y42', got.service) + self.assertEqual('Z42', got.regexp) + self.assertEqual('.42', got.replacement) diff --git a/tests/test_octodns_record_srv.py b/tests/test_octodns_record_srv.py index e525afd..8470a02 100644 --- a/tests/test_octodns_record_srv.py +++ b/tests/test_octodns_record_srv.py @@ -450,3 +450,30 @@ class TestRecordSrv(TestCase): ['Invalid SRV target "100 foo.bar.com." is not a valid FQDN.'], ctx.exception.reasons, ) + + +class TestSrvValue(TestCase): + + def test_template(self): + value = SrvValue( + { + 'priority': 10, + 'weight': 11, + 'port': 12, + 'target': 'no_placeholders', + } + ) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = SrvValue( + { + 'priority': 10, + 'weight': 11, + 'port': 12, + 'target': 'has_{needle}_placeholder', + } + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('has_42_placeholder', got.target) diff --git a/tests/test_octodns_record_sshfp.py b/tests/test_octodns_record_sshfp.py index 4e66186..7364ec1 100644 --- a/tests/test_octodns_record_sshfp.py +++ b/tests/test_octodns_record_sshfp.py @@ -333,3 +333,24 @@ class TestRecordSshfp(TestCase): }, ) self.assertEqual(['missing fingerprint'], ctx.exception.reasons) + + +class TestSshFpValue(TestCase): + + def test_template(self): + value = SshfpValue( + {'algorithm': 10, 'fingerprint_type': 11, 'fingerprint': 'abc123'} + ) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = SshfpValue( + { + 'algorithm': 10, + 'fingerprint_type': 11, + 'fingerprint': 'ab{needle}c123', + } + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('ab42c123', got.fingerprint) diff --git a/tests/test_octodns_record_svcb.py b/tests/test_octodns_record_svcb.py index 2d8cecd..5345b70 100644 --- a/tests/test_octodns_record_svcb.py +++ b/tests/test_octodns_record_svcb.py @@ -673,3 +673,18 @@ class TestRecordSvcb(TestCase): ], ctx.exception.reasons, ) + + +class TestSrvValue(TestCase): + + def test_template(self): + value = SvcbValue({'svcpriority': 0, 'targetname': 'foo.example.com.'}) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = SvcbValue( + {'svcpriority': 0, 'targetname': 'foo.{needle}.example.com.'} + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('foo.42.example.com.', got.targetname) diff --git a/tests/test_octodns_record_target.py b/tests/test_octodns_record_target.py index 715cd4a..6700564 100644 --- a/tests/test_octodns_record_target.py +++ b/tests/test_octodns_record_target.py @@ -5,7 +5,7 @@ from unittest import TestCase from octodns.record.alias import AliasRecord -from octodns.record.target import _TargetValue +from octodns.record.target import _TargetsValue, _TargetValue from octodns.zone import Zone @@ -28,3 +28,33 @@ class TestRecordTarget(TestCase): zone = Zone('unit.tests.', []) a = AliasRecord(zone, 'a', {'ttl': 42, 'value': 'some.target.'}) self.assertEqual('some.target.', a.value.rdata_text) + + +class TestTargetValue(TestCase): + + def test_template(self): + s = 'this.has.no.templating.' + value = _TargetValue(s) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + s = 'this.does.{needle}.have.templating.' + value = _TargetValue(s) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('this.does.42.have.templating.', got) + + +class TestTargetsValue(TestCase): + + def test_template(self): + s = 'this.has.no.templating.' + value = _TargetsValue(s) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + s = 'this.does.{needle}.have.templating.' + value = _TargetsValue(s) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('this.does.42.have.templating.', got) diff --git a/tests/test_octodns_record_tlsa.py b/tests/test_octodns_record_tlsa.py index 26132e8..ef29d5d 100644 --- a/tests/test_octodns_record_tlsa.py +++ b/tests/test_octodns_record_tlsa.py @@ -429,3 +429,32 @@ class TestRecordTlsa(TestCase): 'invalid matching_type "{value["matching_type"]}"', ctx.exception.reasons, ) + + +class TestTlsaValue(TestCase): + + def test_template(self): + value = TlsaValue( + { + 'certificate_usage': 1, + 'selector': 1, + 'matching_type': 1, + 'certificate_association_data': 'ABABABABABABABABAB', + } + ) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = TlsaValue( + { + 'certificate_usage': 1, + 'selector': 1, + 'matching_type': 1, + 'certificate_association_data': 'ABAB{needle}ABABABABABABAB', + } + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual( + 'ABAB42ABABABABABABAB', got.certificate_association_data + ) diff --git a/tests/test_octodns_record_urlfwd.py b/tests/test_octodns_record_urlfwd.py index 6c1f5e1..14f406f 100644 --- a/tests/test_octodns_record_urlfwd.py +++ b/tests/test_octodns_record_urlfwd.py @@ -483,3 +483,33 @@ class TestRecordUrlfwd(TestCase): {'ttl': 32, 'value': UrlfwdValue.parse_rdata_text(rdata)}, ) self.assertEqual(rdata, record.values[0].rdata_text) + + +class TestUrlfwdValue(TestCase): + + def test_template(self): + value = UrlfwdValue( + { + 'path': '/', + 'target': 'http://foo', + 'code': 301, + 'masking': 2, + 'query': 0, + } + ) + got = value.template({'needle': 42}) + self.assertIs(value, got) + + value = UrlfwdValue( + { + 'path': '/{needle}', + 'target': 'http://foo.{needle}', + 'code': 301, + 'masking': 2, + 'query': 0, + } + ) + got = value.template({'needle': 42}) + self.assertIsNot(value, got) + self.assertEqual('/42', got.path) + self.assertEqual('http://foo.42', got.target)