# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # 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 stevedore import extension from designateclient import exceptions from designateclient import utils from designateclient import version class Client(object): """Client for the Designate v1 API""" def __init__(self, endpoint=None, username=None, user_id=None, user_domain_id=None, user_domain_name=None, password=None, tenant_name=None, tenant_id=None, domain_name=None, domain_id=None, project_name=None, project_id=None, project_domain_name=None, project_domain_id=None, auth_url=None, token=None, endpoint_type='publicURL', region_name=None, service_type='dns', insecure=False, session=None, cacert=None, all_tenants=None, edit_managed=None, timeout=None): """ :param endpoint: Endpoint URL :param token: A token instead of username / password :param insecure: Allow "insecure" HTTPS requests """ if endpoint: endpoint = endpoint.rstrip('/') if not endpoint.endswith('v1'): endpoint = "%s/v1" % endpoint # Compatibility code to mimic the old behaviour of the client if session is None: session = utils.get_session( auth_url=auth_url, endpoint=endpoint, domain_id=domain_id, domain_name=domain_name, project_id=project_id or tenant_id, project_name=project_name or tenant_name, project_domain_name=project_domain_name, project_domain_id=project_domain_id, username=username, user_id=user_id, password=password, user_domain_id=user_domain_id, user_domain_name=user_domain_name, token=token, insecure=insecure, cacert=cacert, ) # NOTE: all_tenants and edit_managed are pulled from the session for # backwards compat reasons, do not pull additional modifiers from # here. Once removed, the kwargs above should default to False. if all_tenants is None: self.all_tenants = getattr(session, 'all_tenants', False) else: self.all_tenants = all_tenants if edit_managed is None: self.edit_managed = getattr(session, 'edit_managed', False) else: self.edit_managed = edit_managed # Since we have to behave nicely like a legacy client/bindings we use # an adapter around the session to not modify it's state. interface = endpoint_type.rstrip('URL') self.session = utils.AdapterWithTimeout( session, auth=session.auth, endpoint_override=endpoint, region_name=region_name, service_type=service_type, interface=interface, user_agent='python-designateclient-%s' % version.version_info, version='1', timeout=timeout, ) def _load_controller(ext): controller = ext.plugin(client=self) setattr(self, ext.name, controller) # Load all controllers mgr = extension.ExtensionManager('designateclient.v1.controllers') mgr.map(_load_controller) def wrap_api_call(self, func, *args, **kw): """ Wrap a self. with exception handling :param func: The function to wrap """ kw['raise_exc'] = False kw.setdefault('headers', {}) kw['headers'].setdefault('Content-Type', 'application/json') if self.all_tenants: kw['headers'].update({'X-Auth-All-Projects': 'true'}) if self.edit_managed: kw['headers'].update({'X-Designate-Edit-Managed-Records': 'true'}) # Trigger the request response = func(*args, **kw) # Decode is response, if possible try: response_payload = response.json() except ValueError: response_payload = {} if response.status_code == 400: raise exceptions.BadRequest(**response_payload) elif response.status_code in (401, 403, 413): 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 >= 500: raise exceptions.Unknown(**response_payload) else: return response def get(self, path, **kw): return self.wrap_api_call(self.session.get, path, **kw) def post(self, path, **kw): return self.wrap_api_call(self.session.post, path, **kw) def put(self, path, **kw): return self.wrap_api_call(self.session.put, path, **kw) def delete(self, path, **kw): return self.wrap_api_call(self.session.delete, path, **kw)