class Base(Exception):
class UnsupportedVersion(Base):
class ResourceNotFound(Base):
class NoUniqueMatch(Base):
class RemoteError(Base):
class Unknown(RemoteError):
class BadRequest(RemoteError):
class Forbidden(RemoteError):
class Conflict(RemoteError):
class NotFound(RemoteError):
class OverQuota(RemoteError):
    def __init__(self, message=None):
    def __init__(self, message=None, code=None, type=None, errors=None,
                 request_id=None, **ignore):
    def _get_error_message(self, _message, _type, _errors): class BlacklistController(V2Controller):
    def create(self, pattern, description=None):
        data = {
            'pattern': pattern,
        }

        if description is not None:
            data['description'] = description

        return self._post('/blacklists', data=data)

    def list(self, criterion=None, marker=None, limit=None):
        url = self.build_url('/blacklists', criterion, marker, limit)

        return self._get(url, response_key="blacklists")

    def get(self, blacklist_id):
        url = '/blacklists/%s' % blacklist_id

        return self._get(url)

    def update(self, blacklist_id, values):
        url = '/blacklists/%s' % blacklist_id

        return self._patch(url, data=values)

    def delete(self, blacklist_id):
        url = '/blacklists/%s' % blacklist_id

        return self._delete(url) class LimitController(V2Controller):
    def get(self):
        return self._get('/limits') class NameServerController(V2Controller):
    def list(self, zone):
        zone = v2_utils.resolve_by_name(self.client.zones.list, zone)

        url = '/zones/%s/nameservers' % zone

        return self._get(url, response_key='nameservers') class PoolController(V2Controller):
    def list(self):
        url = '/pools'
        return self._get(url, response_key='pools') class QuotasController(V2Controller):
    def list(self, project_id):
        return self._get('/quotas/%s' % project_id)

    def update(self, project_id, values):
        return self._patch('/quotas/%s' % project_id, data=values)

    def reset(self, project_id):
        return self._delete('/quotas/%s' % project_id) class RecordSetController(V2Controller):
    def _canonicalize_record_name(self, zone, name):
        zone_info = None

        # If we get a zone name we'll need to get the ID of it before POST.
        if isinstance(zone, str) and not \
           uuidutils.is_uuid_like(zone):
            zone_info = self.client.zones.get(zone)
        elif isinstance(zone, dict):
            zone_info = zone

        # We where given a name like "www" vs www.i.io., attempt to fix it on
        # the behalf of the actor.
        if not name.endswith("."):
            if not isinstance(zone_info, dict):
                zone_info = self.client.zones.get(zone)

            name = "%s.%s" % (name, zone_info["name"])

        return name, zone_info

    def create(self, zone, name, type_, records, description=None,
               ttl=None):
        name, zone_info = self._canonicalize_record_name(zone, name)

        data = {
            'name': name,
            'type': type_,
            'records': records
        }

        if ttl is not None:
            data['ttl'] = ttl

        if description is not None:
            data['description'] = description

        if zone_info is not None:
            zone_id = zone_info["id"]
        else:
            zone_id = zone

        url = '/zones/%s/recordsets' % zone_id
        return self._post(url, data=data)

    def list(self, zone, criterion=None, marker=None, limit=None):
        zone = v2_utils.resolve_by_name(self.client.zones.list, zone)

        url = self.build_url(
            '/zones/%s/recordsets' % zone,
            criterion, marker, limit)

        return self._get(url, response_key='recordsets')

    def list_all_zones(self, criterion=None, marker=None, limit=None):

        url = self.build_url('/recordsets', criterion, marker, limit)

        return self._get(url, response_key='recordsets')

    def get(self, zone, recordset):
        zone = v2_utils.resolve_by_name(self.client.zones.list, zone)
        recordset = v2_utils.resolve_by_name(self.list, recordset, zone)

        url = self.build_url('/zones/%s/recordsets/%s' % (
                             zone, recordset))

        return self._get(url)

    def update(self, zone, recordset, values):
        zone = v2_utils.resolve_by_name(self.client.zones.list, zone)
        recordset = v2_utils.resolve_by_name(self.list, recordset, zone)

        url = '/zones/%s/recordsets/%s' % (zone, recordset)

        return self._put(url, data=values)

    def delete(self, zone, recordset):
        zone = v2_utils.resolve_by_name(self.client.zones.list, zone)
        recordset = v2_utils.resolve_by_name(self.list, recordset, zone)

        url = '/zones/%s/recordsets/%s' % (zone, recordset)

        return self._delete(url) class FloatingIPController(V2Controller):
    def set(self, floatingip_id, ptrdname, description=None, ttl=None):
        data = {
            'ptrdname': ptrdname
        }

        if description is not None:
            data["description"] = description

        if ttl is not None:
            data["ttl"] = ttl

        url = '/reverse/floatingips/%s' % floatingip_id
        return self._patch(url, data=data)

    def list(self, criterion=None):
        url = self.build_url('/reverse/floatingips', criterion)

        return self._get(url, response_key='floatingips')

    def get(self, floatingip_id):
        url = '/reverse/floatingips/%s' % floatingip_id

        return self._get(url)

    def unset(self, floatingip_id):
        data = {"ptrdname": None}

        url = '/reverse/floatingips/%s' % floatingip_id

        return self._patch(url, data=data) class ServiceStatusesController(base.V2Controller):
    def list(self, criterion=None, marker=None, limit=None):
        url = self.build_url('/service_statuses', criterion, marker, limit)

        return self._get(url, response_key="service_statuses")

    def get(self, service_status_id):
        url = '/service_statuses/%s' % service_status_id

        return self._get(url) class TLDController(V2Controller):
    def create(self, name, description=None):
        data = {
            'name': name,
        }

        if description is not None:
            data["description"] = description

        return self._post('/tlds', data=data)

    def list(self, criterion=None, marker=None, limit=None):
        url = self.build_url('/tlds', criterion, marker, limit)

        return self._get(url, response_key='tlds')

    def get(self, tld):
        tld = v2_utils.resolve_by_name(self.list, tld)

        return self._get('/tlds/%s' % tld)

    def update(self, tld, values):
        tld = v2_utils.resolve_by_name(self.list, tld)

        return self._patch('/tlds/%s' % tld, data=values)

    def delete(self, tld):
        tld = v2_utils.resolve_by_name(self.list, tld)

        return self._delete('/tlds/%s' % tld) class TSIGKeysController(V2Controller):
    def create(self, name, algorithm, secret, scope, resource_id):
        data = {
            'name': name,
            'algorithm': algorithm,
            'secret': secret,
            'scope': scope,
            'resource_id': resource_id
        }

        return self._post('/tsigkeys', data=data)

    def list(self, criterion=None, marker=None, limit=None):
        url = self.build_url('/tsigkeys', criterion, marker, limit)

        return self._get(url, response_key='tsigkeys')

    def get(self, tsigkey):
        tsigkey = v2_utils.resolve_by_name(self.list, tsigkey)

        return self._get('/tsigkeys/%s' % tsigkey)

    def update(self, tsigkey, values):
        tsigkey = v2_utils.resolve_by_name(self.list, tsigkey)

        return self._patch('/tsigkeys/%s' % tsigkey, data=values)

    def delete(self, tsigkey):
        tsigkey = v2_utils.resolve_by_name(self.list, tsigkey)

        return self._delete('/tsigkeys/%s' % tsigkey) class ZoneController(V2Controller):
    def create(self, name, type_=None, email=None, description=None, ttl=None,
               masters=None, attributes=None):
        type_ = type_ or "PRIMARY"

        data = {
            "name": name,
            "type": type_
        }

        if type_ == "PRIMARY":
            if email:
                data["email"] = email

            if ttl is not None:
                data["ttl"] = ttl

        elif type_ == "SECONDARY" and masters:
            data["masters"] = masters

        if description is not None:
            data["description"] = description

        if attributes is not None:
            data["attributes"] = attributes

        return self._post('/zones', data=data)

    def list(self, criterion=None, marker=None, limit=None):
        url = self.build_url('/zones', criterion, marker, limit)

        return self._get(url, response_key="zones")

    def get(self, zone):
        zone = v2_utils.resolve_by_name(self.list, zone)

        return self._get('/zones/%s' % zone)

    def update(self, zone, values):
        zone = v2_utils.resolve_by_name(self.list, zone)

        url = self.build_url('/zones/%s' % zone)

        return self._patch(url, data=values)

    def delete(self, zone):
        zone = v2_utils.resolve_by_name(self.list, zone)

        url = self.build_url('/zones/%s' % zone)

        return self._delete(url)

    def abandon(self, zone):
        zone = v2_utils.resolve_by_name(self.list, zone)

        url = '/zones/%s/tasks/abandon' % zone

        self.client.session.post(url)

    def axfr(self, zone):
        zone = v2_utils.resolve_by_name(self.list, zone)

        url = '/zones/%s/tasks/xfr' % zone

        self.client.session.post(url) class ZoneExportsController(V2Controller):
    def create(self, zone):
        zone_id = v2_utils.resolve_by_name(self.client.zones.list, zone)

        return self._post('/zones/%s/tasks/export' % zone_id)

    def get_export_record(self, zone_export_id):
        return self._get('/zones/tasks/exports/%s' % zone_export_id)

    def list(self):
        return self._get('/zones/tasks/exports')

    def delete(self, zone_export_id):
        return self._delete('/zones/tasks/exports/%s' % zone_export_id)

    def get_export(self, zone_export_id):
        return self._get('/zones/tasks/exports/%s/export' % zone_export_id,
                         headers={'Accept': 'text/dns'}) class ZoneImportsController(V2Controller):
    def create(self, zone_file_contents):
        return self._post('/zones/tasks/imports', data=zone_file_contents,
                          headers={'Content-Type': 'text/dns'})

    def get_import_record(self, zone_import_id):
        return self._get('/zones/tasks/imports/%s' % zone_import_id)

    def list(self):
        return self._get('/zones/tasks/imports')

    def delete(self, zone_import_id):
        return self._delete('/zones/tasks/imports/%s' % zone_import_id) class ZoneTransfersController(V2Controller):
    def create_request(self, zone, target_project_id, description=None):
        zone = v2_utils.resolve_by_name(self.client.zones.list, zone)

        data = {
            "target_project_id": target_project_id
        }

        if description is not None:
            data["description"] = description

        url = '/zones/%s/tasks/transfer_requests' % zone

        return self._post(url, data=data)

    def get_request(self, transfer_id):
        url = '/zones/tasks/transfer_requests/%s' % transfer_id
        return self._get(url)

    def list_requests(self):
        url = '/zones/tasks/transfer_requests'
        return self._get(url, response_key="transfer_requests")

    def update_request(self, transfer_id, values):
        url = '/zones/tasks/transfer_requests/%s' % transfer_id
        return self._patch(url, data=values)

    def delete_request(self, transfer_id):
        url = '/zones/tasks/transfer_requests/%s' % transfer_id
        self._delete(url)

    def accept_request(self, transfer_id, key):
        url = '/zones/tasks/transfer_accepts'

        data = {
            "key": key,
            "zone_transfer_request_id": transfer_id
        }
        return self._post(url, data=data)

    def get_accept(self, accept_id):
        url = '/zones/tasks/transfer_accepts/%s' % accept_id
        return self._get(url)

    def list_accepts(self):
        url = '/zones/tasks/transfer_accepts'
        return self._get(url, response_key="transfer_accepts")
from keystoneauth1 import adapter
from designateclient import exceptions
from designateclient.v2.blacklists import BlacklistController
from designateclient.v2.limits import LimitController
from designateclient.v2.nameservers import NameServerController
from designateclient.v2.pools import PoolController
from designateclient.v2.quotas import QuotasController
from designateclient.v2.recordsets import RecordSetController
from designateclient.v2.reverse import FloatingIPController
from designateclient.v2.service_statuses import ServiceStatusesController
from designateclient.v2.tlds import TLDController
from designateclient.v2.tsigkeys import TSIGKeysController
from designateclient.v2.zones import ZoneController
from designateclient.v2.zones import ZoneExportsController
from designateclient.v2.zones import ZoneImportsController
from designateclient.v2.zones import ZoneTransfersController
from designateclient import version
from oslo_utils import importutils
#
# 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.


osprofiler_web = importutils.try_import("osprofiler.web")


class DesignateAdapter(adapter.LegacyJsonAdapter):
    """Adapter around LegacyJsonAdapter.

    The user can pass a timeout keyword that will apply only to
    the Designate Client, in order:

    - timeout keyword passed to ``request()``
    - timeout attribute on keystone session
    """
    def __init__(self, *args, **kwargs):
        self.timeout = kwargs.pop('timeout', None)
        self.all_projects = kwargs.pop('all_projects', False)
        self.edit_managed = kwargs.pop('edit_managed', False)
        self.sudo_project_id = kwargs.pop('sudo_project_id', None)
        super(self.__class__, self).__init__(*args, **kwargs)

    def request(self, *args, **kwargs):
        kwargs.setdefault('raise_exc', False)

        if self.timeout is not None:
            kwargs.setdefault('timeout', self.timeout)

        kwargs.setdefault('headers', {})

        if self.all_projects:
            kwargs['headers'].setdefault(
                'X-Auth-All-Projects',
                str(self.all_projects)
            )

        if self.edit_managed:
            kwargs['headers'].setdefault(
                'X-Designate-Edit-Managed-Records',
                str(self.edit_managed)
            )

        if self.sudo_project_id is not None:
            kwargs['headers'].setdefault(
                'X-Auth-Sudo-Project-ID',
                self.sudo_project_id
            )

        kwargs['headers'].setdefault(
            'Content-Type', 'application/json')

        if osprofiler_web:
            kwargs['headers'].update(osprofiler_web.get_trace_id_headers())

        response, body = super(self.__class__, self).request(*args, **kwargs)

        # Decode is response, if possible
        try:
            response_payload = response.json()
        except ValueError:
            response_payload = {}
            body = response.text

        if response.status_code == 400:
            raise exceptions.BadRequest(**response_payload)
        elif response.status_code in (401, 403):
            raise exceptions.Forbidden(**response_payload)
        elif response.status_code == 404:
            raise exceptions.NotFound(**response_payload)
        elif response.status_code == 409:
            raise exceptions.Conflict(**response_payload)
        elif response.status_code == 413:
            raise exceptions.OverQuota(**response_payload)
        elif response.status_code >= 500:
            raise exceptions.Unknown(**response_payload)
        return response, body


class Client(object):
    def __init__(self, region_name=None, endpoint_type='publicURL',
                 extensions=None, service_type='dns', service_name=None,
                 http_log_debug=False, session=None, auth=None, timeout=None,
                 endpoint_override=None, all_projects=False,
                 edit_managed=False, sudo_project_id=None):
        if session is None:
            raise ValueError("A session instance is required")

        self.session = DesignateAdapter(
            session,
            auth=auth,
            region_name=region_name,
            service_type=service_type,
            interface=endpoint_type.rstrip('URL'),
            user_agent='python-designateclient-%s' % version.version_info,
            version=('2'),
            endpoint_override=endpoint_override,
            timeout=timeout,
            all_projects=all_projects,
            edit_managed=edit_managed,
            sudo_project_id=sudo_project_id
        )

        self.blacklists = BlacklistController(self)
        self.floatingips = FloatingIPController(self)
        self.limits = LimitController(self)
        self.nameservers = NameServerController(self)
        self.recordsets = RecordSetController(self)
        self.service_statuses = ServiceStatusesController(self)
        self.tlds = TLDController(self)

        self.zones = ZoneController(self)