Add API_v2 Adapter Objects

* Not used in API yet
* Adds all translation rules

Change-Id: Idac495b185f3ef2e74260178eb1d67efe033e2aa
Partially-Implements: blueprint validation-cleanup
This commit is contained in:
Graham Hayes 2015-03-23 13:58:46 +00:00
parent 1a67e0939e
commit b5e6ba63b5
24 changed files with 1067 additions and 55 deletions

View File

@ -13,3 +13,18 @@
# under the License.
# Base Adapter Class
from designate.objects.adapters.base import DesignateAdapter # noqa
# API v2
from designate.objects.adapters.api_v2.blacklist import BlacklistAPIv2Adapter, BlacklistListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.domain import DomainAPIv2Adapter, DomainListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.floating_ip import FloatingIPAPIv2Adapter, FloatingIPListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.record import RecordAPIv2Adapter, RecordListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.recordset import RecordSetAPIv2Adapter, RecordSetListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.pool import PoolAPIv2Adapter, PoolListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.pool_attribute import PoolAttributeAPIv2Adapter, PoolAttributeListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.pool_ns_record import PoolNsRecordAPIv2Adapter, PoolNsRecordListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.tld import TldAPIv2Adapter, TldListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.tsigkey import TsigKeyAPIv2Adapter, TsigKeyListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.quota import QuotaAPIv2Adapter, QuotaListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.zone_transfer_accept import ZoneTransferAcceptAPIv2Adapter, ZoneTransferAcceptListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.zone_transfer_request import ZoneTransferRequestAPIv2Adapter, ZoneTransferRequestListAPIv2Adapter # noqa
from designate.objects.adapters.api_v2.validation_error import ValidationErrorAPIv2Adapter, ValidationErrorListAPIv2Adapter # noqa

View File

@ -36,6 +36,7 @@ class APIv2Adapter(base.DesignateAdapter):
@classmethod
def _render_list(cls, list_object, *args, **kwargs):
r_list = super(APIv2Adapter, cls)._render_list(
list_object, *args, **kwargs)

View File

@ -0,0 +1,55 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class BlacklistAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.Blacklist
MODIFICATIONS = {
'fields': {
"id": {},
"pattern": {
'read_only': False
},
"description": {
'read_only': False
},
"created_at": {},
"updated_at": {},
},
'options': {
'links': True,
'resource_name': 'blacklist',
'collection_name': 'blacklists',
}
}
class BlacklistListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.BlacklistList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'blacklist',
'collection_name': 'blacklists',
}
}

View File

@ -0,0 +1,86 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class DomainAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.Domain
MODIFICATIONS = {
'fields': {
"id": {},
"pool_id": {},
"project_id": {
'rename': 'tenant_id'
},
"name": {
'immutable': True,
},
"email": {
'read_only': False
},
"description": {
'read_only': False
},
"ttl": {
'read_only': False
},
"serial": {},
"status": {},
"action": {},
"version": {},
"type": {
'immutable': True
},
"masters": {},
"created_at": {},
"updated_at": {},
"transferred_at": {},
},
'options': {
'links': True,
'resource_name': 'zone',
'collection_name': 'zones',
}
}
@classmethod
def _parse_object(cls, values, object, *args, **kwargs):
# TODO(Graham): Remove this when
# https://bugs.launchpad.net/designate/+bug/1432842 is fixed
if 'masters' in values:
object.set_masters(values.get('masters'))
del values['masters']
return super(DomainAPIv2Adapter, cls)._parse_object(
values, object, *args, **kwargs)
class DomainListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.DomainList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'zone',
'collection_name': 'zones',
}
}

View File

@ -0,0 +1,64 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class FloatingIPAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.FloatingIP
MODIFICATIONS = {
'fields': {
"id": {
'rename': 'key'
},
"description": {
'read_only': False
},
"address": {},
"ptrdname": {
'read_only': False
},
"ttl": {
'read_only': False
},
},
'options': {
'links': True,
'resource_name': 'floatingip',
'collection_name': 'floatingips',
}
}
@classmethod
def _get_resource_links(cls, object, request):
return {'self': '%s%s/%s' %
(cls.BASE_URI, cls._get_path(request), object.key)}
class FloatingIPListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.FloatingIPList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'floatingip',
'collection_name': 'floatingips',
}
}

View File

@ -0,0 +1,65 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class PoolAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.Pool
MODIFICATIONS = {
'fields': {
'id': {},
'project_id': {
'immutable': True,
'rename': 'tenant_id'
},
'name': {
'read_only': False
},
'description': {
'read_only': False
},
'attributes': {
'read_only': False
},
'ns_records': {
'read_only': False
},
"created_at": {},
"updated_at": {},
},
'options': {
'links': True,
'resource_name': 'pool',
'collection_name': 'pools',
}
}
class PoolListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.PoolList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'pool',
'collection_name': 'pools',
}
}

View File

@ -0,0 +1,96 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class PoolAttributeAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.PoolAttribute
MODIFICATIONS = {
'fields': {
'key': {
'read_only': False
},
'value': {
'read_only': False
}
},
'options': {
'links': False,
'resource_name': 'pool_attribute',
'collection_name': 'pool_attributes',
}
}
@classmethod
def _render_object(cls, object, *arg, **kwargs):
return {object.key: object.value}
@classmethod
def _parse_object(cls, values, object, *args, **kwargs):
for key in values.keys():
object.key = key
object.value = values[key]
return object
class PoolAttributeListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.PoolAttributeList
MODIFICATIONS = {
'options': {
'links': False,
'resource_name': 'pool_attribute',
'collection_name': 'pool_attributes',
}
}
@classmethod
def _render_list(cls, list_object, *args, **kwargs):
r_list = {}
for object in list_object:
value = cls.get_object_adapter(
cls.ADAPTER_FORMAT,
object).render(cls.ADAPTER_FORMAT, object, *args, **kwargs)
for key in value.keys():
r_list[key] = value[key]
return r_list
@classmethod
def _parse_list(cls, values, output_object, *args, **kwargs):
for key, value in values.iteritems():
# Add the object to the list
output_object.append(
# Get the right Adapter
cls.get_object_adapter(
cls.ADAPTER_FORMAT,
# This gets the internal type of the list, and parses it
# We need to do `get_object_adapter` as we need a new
# instance of the Adapter
output_object.LIST_ITEM_TYPE()).parse(
{key: value}, output_object.LIST_ITEM_TYPE()))
# Return the filled list
return output_object

View File

@ -0,0 +1,60 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class PoolNsRecordAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.PoolNsRecord
MODIFICATIONS = {
'fields': {
'priority': {
'read_only': False
},
'hostname': {
'read_only': False
},
},
'options': {
'links': False,
'resource_name': 'ns_record',
'collection_name': 'ns_records',
}
}
class PoolNsRecordListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.PoolNsRecordList
MODIFICATIONS = {
'options': {
'links': False,
'resource_name': 'ns_record',
'collection_name': 'ns_records',
}
}
@classmethod
def _render_list(cls, list_object, *args, **kwargs):
r_list = super(PoolNsRecordListAPIv2Adapter, cls)._render_list(
list_object, *args, **kwargs)
return r_list[cls.MODIFICATIONS['options']['collection_name']]

View File

@ -0,0 +1,62 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class QuotaAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.Quota
MODIFICATIONS = {
'fields': {
'zones': {
'rename': 'domains',
'read_only': False
},
'zone_records': {
'rename': 'domain_records',
'read_only': False
},
'zone_recordsets': {
'rename': 'domain_recordsets',
'read_only': False
},
'recordset_records': {
'read_only': False
},
},
'options': {
'links': True,
'resource_name': 'quota',
'collection_name': 'quotas',
}
}
class QuotaListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.QuotaList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'quota',
'collection_name': 'quotas',
}
}

View File

@ -0,0 +1,65 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class RecordAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.Record
MODIFICATIONS = {
'fields': {
"data": {
'read_only': False
},
},
'options': {
'links': False,
'resource_name': 'record',
'collection_name': 'records',
}
}
@classmethod
def _render_object(cls, record, *arg, **kwargs):
return record.data
@classmethod
def _parse_object(cls, value, record_object, *args, **kwargs):
record_object.data = value
return record_object
class RecordListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.RecordList
MODIFICATIONS = {
'options': {
'links': False,
'resource_name': 'record',
'collection_name': 'records',
}
}
@classmethod
def _render_list(cls, record_list, *arg, **kwargs):
list = []
for record in record_list:
list.append(record.data)
return list

View File

@ -0,0 +1,111 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
from designate import exceptions
LOG = logging.getLogger(__name__)
class RecordSetAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.RecordSet
MODIFICATIONS = {
'fields': {
"id": {},
"zone_id": {
'rename': 'domain_id'
},
"name": {
'immutable': True
},
"type": {
'rename': 'type',
'immutable': True
},
"records": {
'read_only': False
},
"description": {
'read_only': False
},
"ttl": {
'read_only': False
},
"status": {},
"action": {},
"version": {},
"created_at": {},
"updated_at": {},
},
'options': {
'links': True,
'resource_name': 'recordset',
'collection_name': 'recordsets',
}
}
@classmethod
def _parse_object(cls, new_recordset, recordset, *args, **kwargs):
# TODO(Graham): Remove this when
# https://bugs.launchpad.net/designate/+bug/1432842 is fixed
try:
recordset.records
except exceptions.RelationNotLoaded:
recordset.records = objects.RecordList()
original_records = set()
for record in recordset.records:
original_records.add(record.data)
# Get new list of Records
new_records = set()
if 'records' in new_recordset:
for record in new_recordset['records']:
new_records.add(record)
# Get differences of Records
records_to_add = new_records.difference(original_records)
records_to_rm = original_records.difference(new_records)
# Update all items except records
record_update = False
if 'records' in new_recordset:
record_update = True
del new_recordset['records']
# Remove deleted records if we have provided a records array
if record_update:
recordset.records[:] = [record for record in recordset.records
if record.data not in records_to_rm]
# Add new records
for record in records_to_add:
recordset.records.append(objects.Record(data=record))
return super(RecordSetAPIv2Adapter, cls)._parse_object(
new_recordset, recordset, *args, **kwargs)
class RecordSetListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.RecordSetList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'recordset',
'collection_name': 'recordsets',
}
}

View File

@ -0,0 +1,55 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class TldAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.Tld
MODIFICATIONS = {
'fields': {
"id": {},
"name": {
'read_only': False
},
"description": {
'read_only': False
},
"created_at": {},
"updated_at": {},
},
'options': {
'links': True,
'resource_name': 'tld',
'collection_name': 'tlds',
}
}
class TldListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.TldList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'tld',
'collection_name': 'tlds',
}
}

View File

@ -0,0 +1,64 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class TsigKeyAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.TsigKey
MODIFICATIONS = {
'fields': {
"id": {},
"name": {
'read_only': False
},
"algorithm": {
'read_only': False
},
"secret": {
'read_only': False
},
"scope": {
'read_only': False
},
"resource_id": {
'read_only': False
},
"created_at": {},
"updated_at": {},
},
'options': {
'links': True,
'resource_name': 'tsigkey',
'collection_name': 'tsigkeys',
}
}
class TsigKeyListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.TsigKeyList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'tsigkey',
'collection_name': 'tsigkeys',
}
}

View File

@ -0,0 +1,72 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
LOG = logging.getLogger(__name__)
class ZoneTransferAcceptAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.ZoneTransferAccept
MODIFICATIONS = {
'fields': {
"id": {},
"zone_transfer_request_id": {
'immutable': True
},
"project_id": {
'rename': 'tenant_id',
},
"key": {
'read_only': False
},
"status": {},
"zone_id": {
'rename': 'domain_id',
},
"created_at": {},
"updated_at": {},
},
'options': {
'links': True,
'resource_name': 'transfer_accept',
'collection_name': 'transfer_accepts',
}
}
@classmethod
def _render_object(cls, object, *args, **kwargs):
obj = super(ZoneTransferAcceptAPIv2Adapter, cls)._render_object(
object, *args, **kwargs)
obj['links']['zone'] = \
'%s%s/%s' % (cls.BASE_URI, 'zones', obj['zone_id'])
return obj
class ZoneTransferAcceptListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.ZoneTransferAcceptList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'transfer_accept',
'collection_name': 'transfer_accepts',
}
}

View File

@ -0,0 +1,103 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from designate.objects.adapters.api_v2 import base
from designate import objects
from designate import policy
from designate import exceptions
LOG = logging.getLogger(__name__)
class ZoneTransferRequestAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.ZoneTransferRequest
MODIFICATIONS = {
'fields': {
"id": {
'protected': False
},
"zone_id": {
'rename': 'domain_id',
'immutable': True,
'protected': False
},
"project_id": {
'rename': 'tenant_id',
},
"target_project_id": {
'rename': 'target_tenant_id',
'immutable': True
},
"description": {
'read_only': False,
'protected': False
},
"key": {},
"status": {
'protected': False
},
"zone_name": {
'rename': 'domain_name',
'protected': False
},
"created_at": {},
"updated_at": {},
},
'options': {
'links': True,
'resource_name': 'transfer_request',
'collection_name': 'transfer_requests',
}
}
@classmethod
def _render_object(cls, object, *args, **kwargs):
obj = super(ZoneTransferRequestAPIv2Adapter, cls)._render_object(
object, *args, **kwargs)
try:
target = {
'tenant_id': object.tenant_id,
}
policy.check(
'get_zone_transfer_request_detailed',
kwargs['context'],
target)
except exceptions.Forbidden:
for field in cls.MODIFICATIONS['fields']:
if cls.MODIFICATIONS['fields'][field].get('protected', True):
del obj[field]
return obj
@classmethod
def _get_path(cls, request):
return '/v2/zones/tasks/transfer_requests'
class ZoneTransferRequestListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.ZoneTransferRequestList
MODIFICATIONS = {
'options': {
'links': True,
'resource_name': 'transfer_request',
'collection_name': 'transfer_requests',
}
}

View File

@ -157,11 +157,9 @@ class DesignateAdapter(object):
error_keys = []
for key, value in values.iteritems():
error_flag = True
if key in cls.MODIFICATIONS['fields']:
# No rename needed
obj_key = key
error_flag = False
# This item may need to be translated
if cls.MODIFICATIONS['fields'][key].get('rename', False):
obj_key = cls.MODIFICATIONS['fields'][key].get('rename')
@ -171,46 +169,48 @@ class DesignateAdapter(object):
# is moved into DesignateObjects properly #
##############################################################
# Check if the field should be allowed change after it is initially
# set (eg domain name)
if cls.MODIFICATIONS['fields'][key].get('idempotent', False):
# Check if the field should be allowed change after it is
# initially set (eg domain name)
if cls.MODIFICATIONS['fields'][key].get('immutable', False):
if getattr(output_object, obj_key, False) and \
getattr(output_object, obj_key) != value:
error_keys.append(key)
break
# Is this field a read only field
elif cls.MODIFICATIONS['fields'][key].get('read_only', True) and \
getattr(output_object, obj_key) != value:
elif cls.MODIFICATIONS['fields'][key].get('read_only', True) \
and getattr(output_object, obj_key) != value:
error_keys.append(key)
break
# Check if the key is a nested object
if output_object.FIELDS.get(obj_key, {}).get('relation', False):
if output_object.FIELDS.get(obj_key, {}).get(
'relation', False):
# Get the right class name
obj_class_name = output_object.FIELDS.get(
obj_key, {}).get('relation_cls')
# Get the an instance of it
obj_class = \
objects.DesignateObject.obj_cls_from_name(obj_class_name)
objects.DesignateObject.obj_cls_from_name(
obj_class_name)
# Get the adapted object
obj = \
cls.get_object_adapter(
cls.ADAPTER_FORMAT, obj_class_name).parse(
value, obj_class)
value, obj_class())
# Set the object on the main object
setattr(output_object, obj_key, obj)
else:
# No nested objects here, just set the value
setattr(output_object, obj_key, value)
if error_flag:
else:
# We got an extra key
error_keys.append(key)
if error_keys:
error_message = str.format(
'Provided object does not match schema. Keys {0} are not '
'valid in the request body',
error_keys)
'valid for {1}',
error_keys, cls.MODIFICATIONS['options']['resource_name'])
raise exceptions.InvalidObject(error_message)
@ -218,4 +218,18 @@ class DesignateAdapter(object):
@classmethod
def _parse_list(cls, values, output_object, *args, **kwargs):
raise exceptions.NotImplemented('List adaption not implemented')
for item in values:
# Add the object to the list
output_object.append(
# Get the right Adapter
cls.get_object_adapter(
cls.ADAPTER_FORMAT,
# This gets the internal type of the list, and parses it
# We need to do `get_object_adapter` as we need a new
# instance of the Adapter
output_object.LIST_ITEM_TYPE()).parse(
item, output_object.LIST_ITEM_TYPE()))
# Return the filled list
return output_object

View File

@ -13,7 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from designate import utils
from designate import exceptions
from designate.objects import base
from designate.objects.validation_error import ValidationError
from designate.objects.validation_error import ValidationErrorList
from designate.objects.domain_attribute import DomainAttribute
from designate.objects.domain_attribute import DomainAttributeList
@ -87,7 +90,7 @@ class Domain(base.DictObjectMixin, base.SoftDeleteObjectMixin,
},
'parent_domain_id': {
'schema': {
'type': 'string',
'type': ['string', 'null'],
'format': 'uuid'
},
'read_only': True
@ -135,8 +138,20 @@ class Domain(base.DictObjectMixin, base.SoftDeleteObjectMixin,
'relation': True,
'relation_cls': 'DomainAttributeList'
},
'type': {},
'transferred_at': {},
'type': {
'schema': {
'type': 'string',
'enum': ['SECONDARY', 'PRIMARY'],
},
'immutable': True
},
'transferred_at': {
'schema': {
'type': ['string', 'null'],
'format': 'date-time',
},
'read_only': True
},
}
@property
@ -165,6 +180,21 @@ class Domain(base.DictObjectMixin, base.SoftDeleteObjectMixin,
return srv
return False
def validate(self):
if self.type == 'SECONDARY' and self.masters is None:
errors = ValidationErrorList()
e = ValidationError()
e.absolute_path = ['']
e.validator = 'required'
e.validator_value = ['masters']
e.message = "'masters' is a required property"
errors.append(e)
raise exceptions.InvalidObject(
"Provided object does not match "
"schema", errors=errors, object=self)
super(Domain, self).validate()
class DomainList(base.ListObjectMixin, base.DesignateObject,
base.PagedListObjectMixin):

View File

@ -34,7 +34,7 @@ class FloatingIP(base.DictObjectMixin, base.PersistentObjectMixin,
"id": {
'schema': {
'type': 'string',
'format': 'floating-ip-id'
'format': 'uuid'
}
},
"ptrdname": {
@ -57,6 +57,10 @@ class FloatingIP(base.DictObjectMixin, base.PersistentObjectMixin,
}
}
@property
def key(self):
return '%s:%s' % (self.region, self.id)
class FloatingIPList(base.ListObjectMixin, base.DesignateObject):
LIST_ITEM_TYPE = FloatingIP

View File

@ -24,7 +24,6 @@ class PoolAttribute(base.DictObjectMixin, base.PersistentObjectMixin,
'description': 'Pool identifier',
'format': 'uuid',
},
'required': True
},
'key': {
'schema': {

View File

@ -24,7 +24,6 @@ class PoolNsRecord(base.DictObjectMixin, base.PersistentObjectMixin,
'description': 'Pool identifier',
'format': 'uuid',
},
'required': True
},
'priority': {
'schema': {

View File

@ -26,7 +26,6 @@ class Record(base.DictObjectMixin, base.PersistentObjectMixin,
'type': 'string',
'format': 'uuid',
},
'required': True
},
'managed': {
'schema': {
@ -62,7 +61,6 @@ class Record(base.DictObjectMixin, base.PersistentObjectMixin,
'type': 'string',
'maxLength': 32
},
'required': True
},
'description': {
'schema': {
@ -86,7 +84,6 @@ class Record(base.DictObjectMixin, base.PersistentObjectMixin,
'type': 'string',
'format': 'uuid',
},
'required': True
},
'managed_tenant_id': {
'schema': {

View File

@ -53,7 +53,6 @@ class RecordSet(base.DictObjectMixin, base.PersistentObjectMixin,
'schema': {
'type': 'string',
},
'required': True,
'read_only': True
},
'domain_id': {
@ -62,8 +61,6 @@ class RecordSet(base.DictObjectMixin, base.PersistentObjectMixin,
'description': 'Zone identifier',
'format': 'uuid'
},
'read_only': True,
'required': True
},
'name': {
'schema': {
@ -87,7 +84,7 @@ class RecordSet(base.DictObjectMixin, base.PersistentObjectMixin,
},
'ttl': {
'schema': {
'type': 'integer',
'type': ['integer', 'null'],
'description': 'Default time to live',
'minimum': 0,
'maximum': 2147483647

View File

@ -30,7 +30,6 @@ class ZoneTransferAccept(base.DictObjectMixin, base.PersistentObjectMixin,
'schema': {
'type': 'string',
},
'required': True,
'read_only': True
},
'status': {
@ -57,5 +56,6 @@ class ZoneTransferAccept(base.DictObjectMixin, base.PersistentObjectMixin,
}
class ZoneTransferAcceptList(base.ListObjectMixin, base.DesignateObject):
class ZoneTransferAcceptList(base.ListObjectMixin, base.DesignateObject,
base.PagedListObjectMixin):
LIST_ITEM_TYPE = ZoneTransferAccept

View File

@ -24,7 +24,6 @@ class ZoneTransferRequest(base.DictObjectMixin, base.PersistentObjectMixin,
"type": "string",
"maxLength": 160
},
'required': True
},
'domain_id': {
'schema': {
@ -44,7 +43,6 @@ class ZoneTransferRequest(base.DictObjectMixin, base.PersistentObjectMixin,
'schema': {
'type': 'string',
},
'required': True,
'read_only': True
},
'target_tenant_id': {