# # 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 heat.common.i18n import _ from heat.engine import constraints from heat.engine import properties from heat.engine import resource from heat.engine import support class DesignateRecord(resource.Resource): """Heat Template Resource for Designate Record.""" support_status = support.SupportStatus( version='5.0.0') PROPERTIES = ( NAME, TTL, DESCRIPTION, TYPE, DATA, PRIORITY, DOMAIN ) = ( 'name', 'ttl', 'description', 'type', 'data', 'priority', 'domain' ) _ALLOWED_TYPES = ( A, AAAA, CNAME, MX, SRV, TXT, SPF, NS, PTR, SSHFP, SOA ) = ( 'A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', 'PTR', 'SSHFP', 'SOA' ) properties_schema = { # Based on RFC 1035, length of name is set to max of 255 NAME: properties.Schema( properties.Schema.STRING, _('Record name.'), required=True, constraints=[constraints.Length(max=255)] ), # Based on RFC 1035, range for ttl is set to 0 to signed 32 bit number TTL: properties.Schema( properties.Schema.INTEGER, _('Time To Live (Seconds).'), update_allowed=True, constraints=[constraints.Range(min=0, max=2147483647)] ), # designate mandates to the max length of 160 for description DESCRIPTION: properties.Schema( properties.Schema.STRING, _('Description of record.'), update_allowed=True, constraints=[constraints.Length(max=160)] ), TYPE: properties.Schema( properties.Schema.STRING, _('DNS Record type.'), update_allowed=True, required=True, constraints=[constraints.AllowedValues( _ALLOWED_TYPES )] ), DATA: properties.Schema( properties.Schema.STRING, _('DNS record data, varies based on the type of record. For more ' 'details, please refer rfc 1035.'), update_allowed=True, required=True ), # Based on RFC 1035, range for priority is set to 0 to signed 16 bit # number PRIORITY: properties.Schema( properties.Schema.INTEGER, _('DNS record priority. It is considered only for MX and SRV ' 'types, otherwise, it is ignored.'), update_allowed=True, constraints=[constraints.Range(min=0, max=65536)] ), DOMAIN: properties.Schema( properties.Schema.STRING, _('DNS Domain id or name.'), required=True, constraints=[constraints.CustomConstraint('designate.domain')] ), } default_client_name = 'designate' def handle_create(self): args = dict( name=self.properties[self.NAME], type=self.properties[self.TYPE], description=self.properties[self.DESCRIPTION], ttl=self.properties[self.TTL], data=self.properties[self.DATA], # priority is considered only for MX and SRV record. priority=(self.properties[self.PRIORITY] if self.properties[self.TYPE] in (self.MX, self.SRV) else None), domain=self.properties[self.DOMAIN] ) domain = self.client_plugin().record_create(**args) self.resource_id_set(domain.id) def handle_update(self, json_snippet=None, tmpl_diff=None, prop_diff=None): args = dict() if prop_diff.get(self.TTL): args['ttl'] = prop_diff.get(self.TTL) if prop_diff.get(self.DESCRIPTION): args['description'] = prop_diff.get(self.DESCRIPTION) if prop_diff.get(self.TYPE): args['type'] = prop_diff.get(self.TYPE) # priority is considered only for MX and SRV record. if prop_diff.get(self.PRIORITY): args['priority'] = (prop_diff.get(self.PRIORITY) if (prop_diff.get(self.TYPE) or self.properties[self.TYPE]) in (self.MX, self.SRV) else None) if prop_diff.get(self.DATA): args['data'] = prop_diff.get(self.DATA) if len(args.keys()) > 0: args['id'] = self.resource_id args['domain'] = self.properties[self.DOMAIN] self.client_plugin().record_update(**args) def handle_delete(self): if self.resource_id is not None: try: self.client_plugin().record_delete( id=self.resource_id, domain=self.properties[self.DOMAIN] ) except Exception as ex: self.client_plugin().ignore_not_found(ex) def resource_mapping(): return { 'OS::Designate::Record': DesignateRecord }