diff --git a/designateclient/auth.py b/designateclient/auth.py index 72d8ee3..c7853c2 100644 --- a/designateclient/auth.py +++ b/designateclient/auth.py @@ -13,7 +13,6 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - from urlparse import urlparse from keystoneclient.v2_0.client import Client diff --git a/designateclient/osc/__init__.py b/designateclient/osc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/designateclient/osc/plugin.py b/designateclient/osc/plugin.py new file mode 100644 index 0000000..4b266c5 --- /dev/null +++ b/designateclient/osc/plugin.py @@ -0,0 +1,47 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# Author: Endre Karlson +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from openstackclient.common import utils as oscutils + +from designateclient import shell + + +DEFAULT_API_VERSION = '2' + +API_NAME = 'dns' +API_VERSION_OPTION = 'os_dns_api_version' +API_VERSIONS = { + '2': 'designateclient.v2.client.Client', +} + + +def make_client(instance): + cls = oscutils.get_client_class( + API_NAME, instance._api_version[API_NAME], + API_VERSIONS) + return cls(session=instance.session) + + +def build_option_parser(parser): + """Hook to add global options.""" + parser.add_argument( + '--os-dns-api-version', + metavar='', + default=shell.env('OS_DNS_API_VERSION'), + help='DNS API version, default=' + + DEFAULT_API_VERSION + + ' (Env: OS_DNS_API_VERSION)') + + return parser diff --git a/designateclient/v2/cli/__init__.py b/designateclient/v2/cli/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/designateclient/v2/cli/blacklists.py b/designateclient/v2/cli/blacklists.py new file mode 100644 index 0000000..0de64d4 --- /dev/null +++ b/designateclient/v2/cli/blacklists.py @@ -0,0 +1,126 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# Author: Endre Karlson +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from cliff import command +from cliff import lister +from cliff import show +import six + +from designateclient import utils + +LOG = logging.getLogger(__name__) + + +class ListBlacklistsCommand(lister.Lister): + """List blacklists""" + + columns = ['id', 'pattern', 'description'] + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + cols = self.columns + data = client.blacklists.list() + return cols, (utils.get_item_properties(s, cols) for s in data) + + +class ShowBlacklistCommand(show.ShowOne): + """Show blacklist details""" + + def get_parser(self, prog_name): + parser = super(ShowBlacklistCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Blacklist ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + data = client.blacklists.get(parsed_args.id) + return zip(*sorted(six.iteritems(data))) + + +class CreateBlacklistCommand(show.ShowOne): + """Create new blacklist""" + + def get_parser(self, prog_name): + parser = super(CreateBlacklistCommand, self).get_parser(prog_name) + + parser.add_argument('--pattern', help="Blacklist pattern", + required=True) + parser.add_argument('--description', help="Description") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.blacklists.create( + parsed_args.pattern, parsed_args.description) + + return zip(*sorted(six.iteritems(data))) + + +class SetBlacklistCommand(show.ShowOne): + """Set blacklist properties""" + + def get_parser(self, prog_name): + parser = super(SetBlacklistCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Blacklist ID") + parser.add_argument('--pattern', help="Blacklist pattern", + required=True) + description_group = parser.add_mutually_exclusive_group() + description_group.add_argument('--description', help="Description") + description_group.add_argument('--no-description', action='store_true') + + return parser + + def take_action(self, parsed_args): + data = {} + + if parsed_args.pattern: + data['pattern'] = parsed_args.pattern + + if parsed_args.no_description: + data['description'] = None + elif parsed_args.description: + data['description'] = parsed_args.description + + client = self.app.client_manager.dns + + updated = client.blacklists.update(parsed_args.id, data) + + return zip(*sorted(six.iteritems(updated))) + + +class DeleteBlacklistCommand(command.Command): + """Delete blacklist""" + + def get_parser(self, prog_name): + parser = super(DeleteBlacklistCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Blacklist ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + client.blacklists.delete(parsed_args.id) + + LOG.info('Blacklist %s was deleted', parsed_args.id) diff --git a/designateclient/v2/cli/recordsets.py b/designateclient/v2/cli/recordsets.py new file mode 100644 index 0000000..5af6480 --- /dev/null +++ b/designateclient/v2/cli/recordsets.py @@ -0,0 +1,161 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# Author: Endre Karlson +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from cliff import command +from cliff import lister +from cliff import show +import six + +from designateclient import utils + +LOG = logging.getLogger(__name__) + + +class ListRecordSetsCommand(lister.Lister): + """List recordsets""" + + columns = ['id', 'name', 'type', 'records'] + + def get_parser(self, prog_name): + parser = super(ListRecordSetsCommand, self).get_parser(prog_name) + + parser.add_argument('zone_id', help="Zone ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + cols = self.columns + data = client.recordsets.list(parsed_args.zone_id) + return cols, (utils.get_item_properties(s, cols) for s in data) + + +class ShowRecordSetCommand(show.ShowOne): + """Show recordset details""" + + def get_parser(self, prog_name): + parser = super(ShowRecordSetCommand, self).get_parser(prog_name) + + parser.add_argument('zone_id', help="Zone ID") + parser.add_argument('id', help="RecordSet ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + data = client.recordsets.get(parsed_args.zone_id, parsed_args.id) + return zip(*sorted(six.iteritems(data))) + + +class CreateRecordSetCommand(show.ShowOne): + """Create new recordset""" + + def get_parser(self, prog_name): + parser = super(CreateRecordSetCommand, self).get_parser(prog_name) + + parser.add_argument('zone_id', help="Zone ID") + parser.add_argument('name', help="RecordSet Name") + parser.add_argument('--records', help="RecordSet Records", + nargs='+', required=True) + parser.add_argument('--type', help="RecordSet Type", required=True) + parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") + parser.add_argument('--description', help="Description") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.recordsets.create( + parsed_args.zone_id, + parsed_args.name, + parsed_args.type, + parsed_args.records, + description=parsed_args.description, + ttl=parsed_args.ttl) + + return zip(*sorted(six.iteritems(data))) + + +class SetRecordSetCommand(show.ShowOne): + """Set recordset properties""" + + def get_parser(self, prog_name): + parser = super(SetRecordSetCommand, self).get_parser(prog_name) + + parser.add_argument('zone_id', help="Zone ID") + parser.add_argument('id', help="RecordSet ID") + parser.add_argument('--name', help="RecordSet Name") + parser.add_argument('--records', help="Records", nargs='+') + + description_group = parser.add_mutually_exclusive_group() + description_group.add_argument('--description', help="Description") + description_group.add_argument('--no-description', action='store_true') + + ttl_group = parser.add_mutually_exclusive_group() + ttl_group.add_argument('--ttl', type=int, help="TTL") + ttl_group.add_argument('--no-ttl', action='store_true') + + return parser + + def take_action(self, parsed_args): + data = {} + + if parsed_args.name: + data['name'] = parsed_args.name + + if parsed_args.no_description: + data['description'] = None + elif parsed_args.description: + data['description'] = parsed_args.description + + if parsed_args.no_ttl: + data['ttl'] = None + elif parsed_args.ttl: + data['ttl'] = parsed_args.ttl + + if parsed_args.records: + data['records'] = parsed_args.records + + client = self.app.client_manager.dns + + updated = client.recordsets.update( + parsed_args.zone_id, + parsed_args.id, + data) + + return zip(*sorted(six.iteritems(updated))) + + +class DeleteRecordSetCommand(command.Command): + """Delete recordset""" + + def get_parser(self, prog_name): + parser = super(DeleteRecordSetCommand, self).get_parser(prog_name) + + parser.add_argument('zone_id', help="Zone ID") + parser.add_argument('id', help="RecordSet ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + client.recordsets.delete(parsed_args.zone_id, parsed_args.id) + + LOG.info('RecordSet %s was deleted', parsed_args.id) diff --git a/designateclient/v2/cli/reverse.py b/designateclient/v2/cli/reverse.py new file mode 100644 index 0000000..333c688 --- /dev/null +++ b/designateclient/v2/cli/reverse.py @@ -0,0 +1,114 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# Author: Endre Karlson +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from cliff import command +from cliff import lister +from cliff import show +import six + +from designateclient import utils + +LOG = logging.getLogger(__name__) + + +class ListFloatingIPCommand(lister.Lister): + """List floatingip ptr records""" + + columns = ['id', 'ptrdname', 'description', 'ttl'] + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + cols = self.columns + data = client.floatingips.list() + return cols, (utils.get_item_properties(s, cols) for s in data) + + +class ShowFloatingIPCommand(show.ShowOne): + """Show floatingip ptr record details""" + + def get_parser(self, prog_name): + parser = super(ShowFloatingIPCommand, self).get_parser(prog_name) + + parser.add_argument('floatingip_id', help="Floating IP ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + data = client.floatingips.get(parsed_args.floatingip_id) + return zip(*sorted(six.iteritems(data))) + + +class SetFloatingIPCommand(show.ShowOne): + """Set floatingip ptr record""" + + def get_parser(self, prog_name): + parser = super(SetFloatingIPCommand, self).get_parser(prog_name) + + parser.add_argument('floatingip_id', help="Floating IP ID") + parser.add_argument('ptrdname', help="PTRD Name") + + description_group = parser.add_mutually_exclusive_group() + description_group.add_argument('--description', help="Description") + description_group.add_argument('--no-description', action='store_true') + + ttl_group = parser.add_mutually_exclusive_group() + ttl_group.add_argument('--ttl', type=int, help="TTL") + ttl_group.add_argument('--no-ttl', action='store_true') + + return parser + + def take_action(self, parsed_args): + data = {} + + if parsed_args.no_description: + data['description'] = None + elif parsed_args.description: + data['description'] = parsed_args.description + + if parsed_args.no_ttl: + data['ttl'] = None + elif parsed_args.ttl: + data['ttl'] = parsed_args.ttl + + client = self.app.client_manager.dns + + fip = client.floatingips.set( + parsed_args.floatingip_id, + parsed_args.ptrdname, + parsed_args.description, + parsed_args.ttl) + + return zip(*sorted(six.iteritems(fip))) + + +class UnsetFloatingIPCommand(command.Command): + """Unset floatingip ptr record""" + + def get_parser(self, prog_name): + parser = super(UnsetFloatingIPCommand, self).get_parser(prog_name) + + parser.add_argument('floatingip_id', help="Floating IP ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + client.floatingips.unset(parsed_args.floatingip_id) + LOG.info('FloatingIP PTR %s was unset' % parsed_args.floatingip_id) diff --git a/designateclient/v2/cli/tlds.py b/designateclient/v2/cli/tlds.py new file mode 100644 index 0000000..3c8fe18 --- /dev/null +++ b/designateclient/v2/cli/tlds.py @@ -0,0 +1,121 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# Author: Endre Karlson +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from cliff import command +from cliff import lister +from cliff import show +import six + +from designateclient import utils + +LOG = logging.getLogger(__name__) + + +class ListTLDsCommand(lister.Lister): + """List tlds""" + + columns = ['id', 'name'] + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.tlds.list() + + cols = self.columns + return cols, (utils.get_item_properties(s, cols) for s in data) + + +class ShowTLDCommand(show.ShowOne): + """Show tld details""" + + def get_parser(self, prog_name): + parser = super(ShowTLDCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="TLD ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + data = client.tlds.get(parsed_args.id) + return zip(*sorted(six.iteritems(data))) + + +class CreateTLDCommand(show.ShowOne): + """Create new tld""" + + def get_parser(self, prog_name): + parser = super(CreateTLDCommand, self).get_parser(prog_name) + + parser.add_argument('--name', help="TLD Name", required=True) + parser.add_argument('--description', help="Description") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + data = client.tlds.create(parsed_args.name, parsed_args.description) + return zip(*sorted(six.iteritems(data))) + + +class SetTLDCommand(show.ShowOne): + """Set tld properties""" + + def get_parser(self, prog_name): + parser = super(SetTLDCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="TLD ID") + parser.add_argument('--name', help="TLD Name") + description_group = parser.add_mutually_exclusive_group() + description_group.add_argument('--description', help="Description") + description_group.add_argument('--no-description', action='store_true') + + return parser + + def take_action(self, parsed_args): + data = {} + + if parsed_args.name: + data['name'] = parsed_args.name + + if parsed_args.no_description: + data['description'] = None + elif parsed_args.description: + data['description'] = parsed_args.description + + client = self.app.client_manager.dns + + data = client.tlds.update(parsed_args.id, data) + return zip(*sorted(six.iteritems(data))) + + +class DeleteTLDCommand(command.Command): + """Delete tld""" + + def get_parser(self, prog_name): + parser = super(DeleteTLDCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="TLD ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + client.tlds.delete(parsed_args.id) + + LOG.info('TLD %s was deleted', parsed_args.id) diff --git a/designateclient/v2/cli/zones.py b/designateclient/v2/cli/zones.py new file mode 100644 index 0000000..cfdeec1 --- /dev/null +++ b/designateclient/v2/cli/zones.py @@ -0,0 +1,393 @@ +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# +# Author: Endre Karlson +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from cliff import command +from cliff import lister +from cliff import show +from openstackclient.common import exceptions as osc_exc +import six + +from designateclient import utils + +LOG = logging.getLogger(__name__) + + +class ListZonesCommand(lister.Lister): + """List zones""" + + columns = ['id', 'name', 'type', 'serial', 'status', 'action'] + + def get_parser(self, prog_name): + parser = super(ListZonesCommand, self).get_parser(prog_name) + + parser.add_argument('--type', help="Zone Type", required=False) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + criterion = {} + if parsed_args.type is not None: + criterion["type"] = parsed_args.type + + data = client.zones.list(criterion=criterion) + + cols = self.columns + return cols, (utils.get_item_properties(s, cols) for s in data) + + +class ShowZoneCommand(show.ShowOne): + """Show zone details""" + + def get_parser(self, prog_name): + parser = super(ShowZoneCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.zones.get(parsed_args.id) + + return zip(*sorted(six.iteritems(data))) + + +class CreateZoneCommand(show.ShowOne): + """Create new zone""" + + def get_parser(self, prog_name): + parser = super(CreateZoneCommand, self).get_parser(prog_name) + + parser.add_argument('name', help="Zone Name") + parser.add_argument('--email', help="Zone Email") + parser.add_argument('--type', help="Zone Type", default='PRIMARY') + parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") + parser.add_argument('--description', help="Description") + parser.add_argument('--masters', help="Zone Masters", nargs='+') + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + payload = {} + + if parsed_args.description: + payload["description"] = parsed_args.description + + if parsed_args.type == 'PRIMARY': + # email is just for PRIMARY. + if not parsed_args.email: + msg = "Zone type PRIMARY requires --email." + raise osc_exc.CommandError(msg) + + payload["email"] = parsed_args.email + + # TTL is just valid for PRIMARY + if parsed_args.ttl is not None: + payload["ttl"] = parsed_args.ttl + elif parsed_args.type == 'SECONDARY': + payload["masters"] = parsed_args.masters + else: + msg = "Type %s is not supported. Please choose between " \ + "PRIMARY or SECONDARY" + raise osc_exc.CommandError(msg) + + data = client.zones.create( + parsed_args.name, parsed_args.type, **payload) + return zip(*sorted(six.iteritems(data))) + + +class SetZoneCommand(show.ShowOne): + """Set zone properties""" + + def get_parser(self, prog_name): + parser = super(SetZoneCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone ID") + parser.add_argument('--name', help="Zone Name") + parser.add_argument('--email', help="Zone Email") + parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") + description_group = parser.add_mutually_exclusive_group() + description_group.add_argument('--description', help="Description") + description_group.add_argument('--no-description', action='store_true') + + parser.add_argument('--masters', help="Zone Masters", nargs='+') + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = {} + + # TODO(kiall): API needs updating.. this get is silly + if parsed_args.name: + data['name'] = parsed_args.name + + if parsed_args.email: + data['email'] = parsed_args.email + + if parsed_args.ttl: + data['ttl'] = parsed_args.ttl + + if parsed_args.no_description: + data['description'] = None + elif parsed_args.description: + data['description'] = parsed_args.description + + if parsed_args.masters: + data['masters'] = parsed_args.masters + + updated = client.zones.update(parsed_args.id, data) + return zip(*sorted(six.iteritems(updated))) + + +class DeleteZoneCommand(command.Command): + """Delete zone""" + + def get_parser(self, prog_name): + parser = super(DeleteZoneCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + client.zones.delete(parsed_args.id) + LOG.info('Zone %s was deleted', parsed_args.id) + + +class ExportZoneCommand(command.Command): + """Export a zone.""" + def get_parser(self, prog_name): + parser = super(ExportZoneCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + response, _ = client.zones.export(parsed_args.id) + print(response.content) + + +class ImportZoneCommand(command.Command): + """Import a zone""" + def get_parser(self, prog_name): + parser = super(ImportZoneCommand, self).get_parser(prog_name) + + parser.add_argument('--path', help="Path to zone file", required=True) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + with open(parsed_args.path) as contents: + client.zones.import_(contents) + LOG.info("Imported zone successfully") + + +class AbandonZoneCommand(command.Command): + """Abandon a zone""" + def get_parser(self, prog_name): + parser = super(AbandonZoneCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + client.zones.abandon(parsed_args.id) + + LOG.info("Z %(zone_id)s abandoned" % + {"zone_id": parsed_args.id}) + + +class AXFRZoneCommand(command.Command): + """AXFR a zone""" + def get_parser(self, prog_name): + parser = super(AXFRZoneCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + client.zones.axfr(parsed_args.id) + + LOG.info("Scheduled AXFR for zone %(zone_id)s" % + {"zone_id": parsed_args.id}) + + +class CreateTransferRequestCommand(show.ShowOne): + """Create new zone transfer request""" + + def get_parser(self, prog_name): + parser = super(CreateTransferRequestCommand, self).get_parser( + prog_name) + + parser.add_argument('zone_id', help="Zone ID to transfer.",) + parser.add_argument( + '--target-project-id', + help="Target Project ID to transfer to.", + required=True) + parser.add_argument('--description', help="Description") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.zone_transfers.create_request( + parsed_args.zone_id, parsed_args.target_project_id, + parsed_args.description) + return zip(*sorted(six.iteritems(data))) + + +class ListTransferRequestsCommand(lister.Lister): + """List zone transfer requests""" + + columns = ['id', 'zone_id', 'zone_name', 'project_id', + 'target_project_id', 'status', 'key'] + + def get_parser(self, prog_name): + parser = super(ListTransferRequestsCommand, self).get_parser( + prog_name) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.zone_transfers.list_requests() + + cols = self.columns + return cols, (utils.get_item_properties(s, cols) for s in data) + + +class ShowTransferRequestCommand(show.ShowOne): + """Show zonet transfer details""" + + def get_parser(self, prog_name): + parser = super(ShowTransferRequestCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone Tranfer ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.zone_transfers.get_request(parsed_args.id) + + return zip(*sorted(six.iteritems(data))) + + +class SetTransferRequestCommand(command.Command): + """Set Transfer""" + + def get_parser(self, prog_name): + parser = super(SetTransferRequestCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone Transfer ID") + description_group = parser.add_mutually_exclusive_group() + description_group.add_argument('--description', help="Description") + description_group.add_argument('--no-description', action='store_true') + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = {} + + if parsed_args.no_description: + data['description'] = None + elif parsed_args.description: + data['description'] = parsed_args.description + + updated = client.zone_transfers.update_request(parsed_args.id, data) + return zip(*sorted(six.iteritems(updated))) + + +class DeleteTransferRequestCommand(command.Command): + def get_parser(self, prog_name): + parser = super(DeleteTransferRequestCommand, self).get_parser( + prog_name) + + parser.add_argument('id', help="Zone Transfer ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + client.zone_transfers.delete_request(parsed_args.id) + + LOG.info('Zone Transfer %s was deleted' % parsed_args.id) + + +class AcceptTransferRequestCommand(command.Command): + """Accept a Zone Transfer Request""" + + def get_parser(self, prog_name): + parser = super(AcceptTransferRequestCommand, self).get_parser( + prog_name) + + parser.add_argument('--transfer-id', help="Transfer ID", type=str, + required=True) + parser.add_argument('--key', help="Transfer Key", type=str, + required=True) + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.zone_transfers.accept_request( + parsed_args.transfer_id, parsed_args.key) + return zip(*sorted(six.iteritems(data))) + + +class ShowTransferAcceptCommand(show.ShowOne): + """Show Zone Transfer Accept""" + + def get_parser(self, prog_name): + parser = super(ShowTransferAcceptCommand, self).get_parser(prog_name) + + parser.add_argument('id', help="Zone Tranfer Accept ID") + + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.dns + + data = client.zone_transfers.get_accept(parsed_args.id) + + return zip(*sorted(six.iteritems(data))) diff --git a/doc/source/bindings.rst b/doc/source/bindings.rst index e977cb3..6795d04 100644 --- a/doc/source/bindings.rst +++ b/doc/source/bindings.rst @@ -6,6 +6,34 @@ The python-designateclient package comes with python bindings for the Designate API. This can be used to interact with the Designate API from any python program. +Introduction - Bindings v2 +========================== + +To view examples of usage please checkout the *doc/examples* folder, basic usage is: + +.. code-block:: python + + #!/usr/bin/env python + from designateclient.v2 import client + from designateclient import shell + + from keystoneclient.auth.identity import generic + from keystoneclient import session as keystone_session + + auth = generic.Password( + auth_url=shell.env('OS_AUTH_URL'), + username=shell.env('OS_USERNAME'), + password=shell.env('OS_PASSWORD'), + tenant_name=shell.env('OS_TENANT_NAME')) + + session = keystone_session.Session(auth=auth) + + client = client.Client(session=session) + + zone = client.zones.create('i.io.', email='i@i.io') + + rs = client.recordsets.create(zone['id'], 'www', 'A', ['10.0.0.1']) + Introduction ============ diff --git a/doc/source/index.rst b/doc/source/index.rst index 9ed8055..b252f5b 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -19,6 +19,7 @@ Contents bindings shell shell-examples + shell-v2 contributing Indices and tables diff --git a/doc/source/shell-v2.rst b/doc/source/shell-v2.rst new file mode 100644 index 0000000..652ecac --- /dev/null +++ b/doc/source/shell-v2.rst @@ -0,0 +1,43 @@ +============================= +designate v2 cli and examples +============================= + +In order to use the v2 you need *python-openstackclient* available. + +:: + + $ pip install python-openstackclient + + +Using the client +---------------- + +Source credentials first + +:: + + $ source ~/openrc + +Or you can use the ~/.config/openstack/clouds.yaml approach. + +.. note:: + + This required you to pass in --os-cloud after the "openstack" part. + +We can now try to create a primary zone + +.. code-block:: shell-session + + $ openstack zone create --name example.net. --email foo@example.org + +Create a A type recordset with some records in it. + +.. code-block:: shell-session + + $ openstack recordset create example.net --type A --name www --records 10.0.0.1 10.0.0.2 + +Set a PTR record for a Floating IP + +.. code-block:: shell-session + + $ openstack ptr record set RegionOne:5c02c519-4928-4a38-bd10-c748c200912f mail.example.net. diff --git a/setup.cfg b/setup.cfg index a329f63..4577a8f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -83,6 +83,50 @@ designateclient.versions = 1 = designateclient.v1:Client 2 = designateclient.v2.client:Client +openstack.cli.extension = + dns = designateclient.osc.plugin + +openstack.dns.v2 = + zone_blacklist_create = designateclient.v2.cli.blacklists:CreateBlacklistCommand + zone_blacklist_list = designateclient.v2.cli.blacklists:ListBlacklistsCommand + zone_blacklist_show = designateclient.v2.cli.blacklists:ShowBlacklistCommand + zone_blacklist_set = designateclient.v2.cli.blacklists:SetBlacklistCommand + zone_blacklist_delete = designateclient.v2.cli.blacklists:DeleteBlacklistCommand + + tld_create = designateclient.v2.cli.tlds:CreateTLDCommand + tld_list = designateclient.v2.cli.tlds:ListTLDsCommand + tld_show = designateclient.v2.cli.tlds:ShowTLDCommand + tld_set = designateclient.v2.cli.tlds:SetTLDCommand + tld_delete = designateclient.v2.cli.tlds:DeleteTLDCommand + + zone_create = designateclient.v2.cli.zones:CreateZoneCommand + zone_list = designateclient.v2.cli.zones:ListZonesCommand + zone_show = designateclient.v2.cli.zones:ShowZoneCommand + zone_set = designateclient.v2.cli.zones:SetZoneCommand + zone_delete = designateclient.v2.cli.zones:DeleteZoneCommand + + zone_abandon = designateclient.v2.cli.zones:AbandonZoneCommand + zone_axfr = designateclient.v2.cli.zones:AXFRZoneCommand + + zone_transfer_request_create = designateclient.v2.cli.zones:CreateTransferRequestCommand + zone_transfer_request_list = designateclient.v2.cli.zones:ListTransferRequestsCommand + zone_transfer_request_show = designateclient.v2.cli.zones:ShowTransferRequestCommand + zone_transfer_request_set = designateclient.v2.cli.zones:SetTransferRequestCommand + zone_transfer_request_delete = designateclient.v2.cli.zones:DeleteTransferRequestCommand + zone_transfer_accept_request = designateclient.v2.cli.zones:AcceptTransferRequestCommand + zone_transfer_accept_show = designateclient.v2.cli.zones:ShowTransferAcceptCommand + + recordset_create = designateclient.v2.cli.recordsets:CreateRecordSetCommand + recordset_list = designateclient.v2.cli.recordsets:ListRecordSetsCommand + recordset_show = designateclient.v2.cli.recordsets:ShowRecordSetCommand + recordset_set = designateclient.v2.cli.recordsets:SetRecordSetCommand + recordset_delete = designateclient.v2.cli.recordsets:DeleteRecordSetCommand + + ptr_record_list = designateclient.v2.cli.reverse:ListFloatingIPCommand + ptr_record_show = designateclient.v2.cli.reverse:ShowFloatingIPCommand + ptr_record_set = designateclient.v2.cli.reverse:SetFloatingIPCommand + ptr_record_unset = designateclient.v2.cli.reverse:UnsetFloatingIPCommand + [build_sphinx] all_files = 1 build-dir = doc/build