diff --git a/examples/zone-export.py b/examples/zone-export.py new file mode 100644 index 0000000..3c2a2b5 --- /dev/null +++ b/examples/zone-export.py @@ -0,0 +1,25 @@ +# +# Copyright (c) 2025 NSONE, Inc. +# +# License under The MIT License (MIT). See LICENSE in project root. +# + +from ns1 import NS1 + +# NS1 will use config in ~/.nsone by default +api = NS1() + +# to specify an apikey here instead, use: +# api = NS1(apiKey='<>') + +# to load an alternate configuration file: +# api = NS1(configFile='/etc/ns1/api.json') + +# export a zone to BIND format +zone = api.loadZone("example.com") +zone_file = zone.export() +print(zone_file) + +# save to a file +with open("example.com.zone", "w") as f: + f.write(zone_file) diff --git a/ns1/rest/zones.py b/ns1/rest/zones.py index 07f01fe..a76e169 100644 --- a/ns1/rest/zones.py +++ b/ns1/rest/zones.py @@ -188,6 +188,20 @@ def delete_version(self, zone, version_id, callback=None, errback=None): errback=errback, ) + def export(self, zone, callback=None, errback=None): + """ + Export zone as BIND-compatible zone file. + + :param str zone: zone name + :return: zone file content as string + """ + return self._make_request( + "GET", + f"{self.ROOT}/{zone}/export", + callback=callback, + errback=errback, + ) + # successive pages just extend the list of zones def zone_list_pagination(curr_json, next_json): diff --git a/ns1/zones.py b/ns1/zones.py index 3e5a8d8..1bd42ef 100644 --- a/ns1/zones.py +++ b/ns1/zones.py @@ -287,3 +287,13 @@ def usage(self, callback=None, errback=None, **kwargs): return stats.usage( zone=self.zone, callback=callback, errback=errback, **kwargs ) + + def export(self, callback=None, errback=None): + """ + Export zone as a BIND-compatible zone file. + + :param callback: optional callback + :param errback: optional error callback + :return: zone file content as string + """ + return self._rest.export(self.zone, callback=callback, errback=errback) diff --git a/tests/unit/test_zone.py b/tests/unit/test_zone.py index 5dae71d..92dbb2b 100644 --- a/tests/unit/test_zone.py +++ b/tests/unit/test_zone.py @@ -251,3 +251,18 @@ def test_rest_zone_buildbody(zones_config): "tags": {"foo": "bar", "hai": "bai"}, } assert z._buildBody(zone, **kwargs) == body + + +@pytest.mark.parametrize( + "zone, url", [("test.zone", "zones/test.zone/export")] +) +def test_rest_zone_export(zones_config, zone, url): + z = ns1.rest.zones.Zones(zones_config) + z._make_request = mock.MagicMock() + z.export(zone) + z._make_request.assert_called_once_with( + "GET", + url, + callback=None, + errback=None, + )