From 8988d9b4cafaa56d4b1702d44a8d9386c4168010 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Tue, 4 Jun 2024 13:58:03 -0700 Subject: [PATCH 1/6] Quick pass at implementing PlanJson --- octodns/provider/plan.py | 16 ++++++++++++++++ tests/test_octodns_plan.py | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/octodns/provider/plan.py b/octodns/provider/plan.py index 825204c..5c33460 100644 --- a/octodns/provider/plan.py +++ b/octodns/provider/plan.py @@ -2,7 +2,9 @@ # # +from collections import defaultdict from io import StringIO +from json import dumps from logging import DEBUG, ERROR, INFO, WARN, getLogger from sys import stdout @@ -220,6 +222,20 @@ def _value_stringifier(record, sep): return sep.join(values) +class PlanJson(_PlanOutput): + def __init__(self, name, indent=None, sort_keys=True): + super().__init__(name) + self.indent = indent + self.sort_keys = sort_keys + + def run(self, plans, fh=stdout, *args, **kwargs): + data = defaultdict(dict) + for target, plan in plans: + data[target.id][plan.desired.name] = plan.data + + fh.write(dumps(data, indent=self.indent, sort_keys=self.sort_keys)) + + class PlanMarkdown(_PlanOutput): def run(self, plans, fh=stdout, *args, **kwargs): if plans: diff --git a/tests/test_octodns_plan.py b/tests/test_octodns_plan.py index 2fda278..21240a0 100644 --- a/tests/test_octodns_plan.py +++ b/tests/test_octodns_plan.py @@ -3,6 +3,7 @@ # from io import StringIO +from json import loads from logging import getLogger from unittest import TestCase @@ -11,6 +12,7 @@ from helpers import SimpleProvider from octodns.provider.plan import ( Plan, PlanHtml, + PlanJson, PlanLogger, PlanMarkdown, RootNsChange, @@ -126,6 +128,17 @@ class TestPlanHtml(TestCase): ) +class TestPlanJson(TestCase): + def test_basics(self): + out = StringIO() + PlanJson('json').run(plans, fh=out) + data = loads(out.getvalue()) + for key in ('test', 'unit.tests.', 'changes'): + self.assertTrue(key in data) + data = data[key] + self.assertEqual(4, len(data)) + + class TestPlanMarkdown(TestCase): log = getLogger('TestPlanMarkdown') From 6cc0945805398d261e269d5df7d635380a48231d Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Tue, 4 Jun 2024 14:00:17 -0700 Subject: [PATCH 2/6] Newline after json blob --- octodns/provider/plan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/octodns/provider/plan.py b/octodns/provider/plan.py index 5c33460..18939c8 100644 --- a/octodns/provider/plan.py +++ b/octodns/provider/plan.py @@ -234,6 +234,7 @@ class PlanJson(_PlanOutput): data[target.id][plan.desired.name] = plan.data fh.write(dumps(data, indent=self.indent, sort_keys=self.sort_keys)) + fh.write('\n') class PlanMarkdown(_PlanOutput): From 3f7af27537907a717d49452793d9f66287b1cd46 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Wed, 5 Jun 2024 10:26:01 -0700 Subject: [PATCH 3/6] Include record_type in change data --- octodns/record/change.py | 13 +++++++++++-- tests/test_octodns_plan.py | 13 ++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/octodns/record/change.py b/octodns/record/change.py index ec9889c..83393e9 100644 --- a/octodns/record/change.py +++ b/octodns/record/change.py @@ -27,7 +27,11 @@ class Create(Change): @property def data(self): - return {'type': 'create', 'new': self.new.data} + return { + 'type': 'create', + 'new': self.new.data, + 'record_type': self.new._type, + } def __repr__(self, leader=''): source = self.new.source.id if self.new.source else '' @@ -43,6 +47,7 @@ class Update(Change): 'type': 'update', 'existing': self.existing.data, 'new': self.new.data, + 'record_type': self.new._type, } # Leader is just to allow us to work around heven eating leading whitespace @@ -65,7 +70,11 @@ class Delete(Change): @property def data(self): - return {'type': 'delete', 'existing': self.existing.data} + return { + 'type': 'delete', + 'existing': self.existing.data, + 'record_type': self.existing._type, + } def __repr__(self, leader=''): return f'Delete {self.existing}' diff --git a/tests/test_octodns_plan.py b/tests/test_octodns_plan.py index 21240a0..943d4af 100644 --- a/tests/test_octodns_plan.py +++ b/tests/test_octodns_plan.py @@ -407,18 +407,25 @@ class TestPlanSafety(TestCase): # we'll test the change .data's here while we're at it since they don't # have a dedicated test (file) delete_data = data['changes'][0] # delete - self.assertEqual(['existing', 'type'], sorted(delete_data.keys())) + self.assertEqual( + ['existing', 'record_type', 'type'], sorted(delete_data.keys()) + ) self.assertEqual('delete', delete_data['type']) + self.assertEqual('A', delete_data['record_type']) self.assertEqual(delete.existing.data, delete_data['existing']) create_data = data['changes'][1] # create - self.assertEqual(['new', 'type'], sorted(create_data.keys())) + self.assertEqual( + ['new', 'record_type', 'type'], sorted(create_data.keys()) + ) self.assertEqual('create', create_data['type']) + self.assertEqual('CNAME', create_data['record_type']) self.assertEqual(create.new.data, create_data['new']) update_data = data['changes'][3] # update self.assertEqual( - ['existing', 'new', 'type'], sorted(update_data.keys()) + ['existing', 'new', 'record_type', 'type'], + sorted(update_data.keys()), ) self.assertEqual('update', update_data['type']) self.assertEqual(update.existing.data, update_data['existing']) From 133c8a2101c29e2673927bb32f801d641a005cd0 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Wed, 5 Jun 2024 10:27:09 -0700 Subject: [PATCH 4/6] Update changelog w/ PlanJson/record_type --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f727f41..97f8a5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ * Allow DS records to be specified for managed sub-zones, same as NS * Fix CAA rdata parsing to allow values with tags +* Include `record_type` in Change data +* Add PlanJson plan_output support ## v1.7.0 - 2024-04-29 - All the knobs and dials From e8764ac1c5ae651099377d3226d9da0a9df25ca8 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Mon, 10 Jun 2024 07:50:18 -0700 Subject: [PATCH 5/6] Move changelog entry --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b1ada..0794cd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,13 @@ +## v1.?.? - 2024-??-?? - ??? + +* Add PlanJson plan_output support + ## v1.8.0 - 2024-06-10 - Set the records straight * Add support for SVCB and HTTPS records * Allow DS records to be specified for managed sub-zones, same as NS * Fix CAA rdata parsing to allow values with tags * Include `record_type` in Change data -* Add PlanJson plan_output support ## v1.7.0 - 2024-04-29 - All the knobs and dials From 00235e6641a99244688c98ce9b1f3284bf25b4f0 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Mon, 10 Jun 2024 12:45:17 -0700 Subject: [PATCH 6/6] Move record_type mention as well --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6107905..3e959ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,13 @@ * Improved handling of present, but empty/None config file values. * Add PlanJson plan_output support - +* Include `record_type` in Change data + ## v1.8.0 - 2024-06-10 - Set the records straight * Add support for SVCB and HTTPS records * Allow DS records to be specified for managed sub-zones, same as NS * Fix CAA rdata parsing to allow values with tags -* Include `record_type` in Change data ## v1.7.0 - 2024-04-29 - All the knobs and dials