Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/boto/route53/connection.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
| author | shellac |
|---|---|
| date | Thu, 14 May 2020 14:56:58 -0400 |
| parents | 26e78fe6e8c4 |
| children |
comparison
equal
deleted
inserted
replaced
| 1:75ca89e9b81c | 2:6af9afd405e9 |
|---|---|
| 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ | |
| 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. | |
| 3 # Copyright (c) 2011 Blue Pines Technologies LLC, Brad Carleton | |
| 4 # www.bluepines.org | |
| 5 # Copyright (c) 2012 42 Lines Inc., Jim Browne | |
| 6 # | |
| 7 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 # copy of this software and associated documentation files (the | |
| 9 # "Software"), to deal in the Software without restriction, including | |
| 10 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 11 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 12 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 13 # lowing conditions: | |
| 14 # | |
| 15 # The above copyright notice and this permission notice shall be included | |
| 16 # in all copies or substantial portions of the Software. | |
| 17 # | |
| 18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 19 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 20 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 21 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 22 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 23 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 24 # IN THE SOFTWARE. | |
| 25 # | |
| 26 | |
| 27 from boto.route53 import exception | |
| 28 import random | |
| 29 import uuid | |
| 30 import xml.sax | |
| 31 | |
| 32 import boto | |
| 33 from boto.connection import AWSAuthConnection | |
| 34 from boto import handler | |
| 35 import boto.jsonresponse | |
| 36 from boto.route53.record import ResourceRecordSets | |
| 37 from boto.route53.zone import Zone | |
| 38 from boto.compat import six, urllib | |
| 39 | |
| 40 | |
| 41 HZXML = """<?xml version="1.0" encoding="UTF-8"?> | |
| 42 <CreateHostedZoneRequest xmlns="%(xmlns)s"> | |
| 43 <Name>%(name)s</Name> | |
| 44 <CallerReference>%(caller_ref)s</CallerReference> | |
| 45 <HostedZoneConfig> | |
| 46 <Comment>%(comment)s</Comment> | |
| 47 </HostedZoneConfig> | |
| 48 </CreateHostedZoneRequest>""" | |
| 49 | |
| 50 HZPXML = """<?xml version="1.0" encoding="UTF-8"?> | |
| 51 <CreateHostedZoneRequest xmlns="%(xmlns)s"> | |
| 52 <Name>%(name)s</Name> | |
| 53 <VPC> | |
| 54 <VPCId>%(vpc_id)s</VPCId> | |
| 55 <VPCRegion>%(vpc_region)s</VPCRegion> | |
| 56 </VPC> | |
| 57 <CallerReference>%(caller_ref)s</CallerReference> | |
| 58 <HostedZoneConfig> | |
| 59 <Comment>%(comment)s</Comment> | |
| 60 </HostedZoneConfig> | |
| 61 </CreateHostedZoneRequest>""" | |
| 62 | |
| 63 # boto.set_stream_logger('dns') | |
| 64 | |
| 65 | |
| 66 class Route53Connection(AWSAuthConnection): | |
| 67 DefaultHost = 'route53.amazonaws.com' | |
| 68 """The default Route53 API endpoint to connect to.""" | |
| 69 | |
| 70 Version = '2013-04-01' | |
| 71 """Route53 API version.""" | |
| 72 | |
| 73 XMLNameSpace = 'https://route53.amazonaws.com/doc/2013-04-01/' | |
| 74 """XML schema for this Route53 API version.""" | |
| 75 | |
| 76 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, | |
| 77 port=None, proxy=None, proxy_port=None, | |
| 78 host=DefaultHost, debug=0, security_token=None, | |
| 79 validate_certs=True, https_connection_factory=None, | |
| 80 profile_name=None): | |
| 81 super(Route53Connection, self).__init__( | |
| 82 host, | |
| 83 aws_access_key_id, aws_secret_access_key, | |
| 84 True, port, proxy, proxy_port, debug=debug, | |
| 85 security_token=security_token, | |
| 86 validate_certs=validate_certs, | |
| 87 https_connection_factory=https_connection_factory, | |
| 88 profile_name=profile_name) | |
| 89 | |
| 90 def _required_auth_capability(self): | |
| 91 return ['route53'] | |
| 92 | |
| 93 def make_request(self, action, path, headers=None, data='', params=None): | |
| 94 if params: | |
| 95 pairs = [] | |
| 96 for key, val in six.iteritems(params): | |
| 97 if val is None: | |
| 98 continue | |
| 99 pairs.append(key + '=' + urllib.parse.quote(str(val))) | |
| 100 path += '?' + '&'.join(pairs) | |
| 101 return super(Route53Connection, self).make_request( | |
| 102 action, path, headers, data, | |
| 103 retry_handler=self._retry_handler) | |
| 104 | |
| 105 # Hosted Zones | |
| 106 | |
| 107 def get_all_hosted_zones(self, start_marker=None, zone_list=None): | |
| 108 """ | |
| 109 Returns a Python data structure with information about all | |
| 110 Hosted Zones defined for the AWS account. | |
| 111 | |
| 112 :param int start_marker: start marker to pass when fetching additional | |
| 113 results after a truncated list | |
| 114 :param list zone_list: a HostedZones list to prepend to results | |
| 115 """ | |
| 116 params = {} | |
| 117 if start_marker: | |
| 118 params = {'marker': start_marker} | |
| 119 response = self.make_request('GET', '/%s/hostedzone' % self.Version, | |
| 120 params=params) | |
| 121 body = response.read() | |
| 122 boto.log.debug(body) | |
| 123 if response.status >= 300: | |
| 124 raise exception.DNSServerError(response.status, | |
| 125 response.reason, | |
| 126 body) | |
| 127 e = boto.jsonresponse.Element(list_marker='HostedZones', | |
| 128 item_marker=('HostedZone',)) | |
| 129 h = boto.jsonresponse.XmlHandler(e, None) | |
| 130 h.parse(body) | |
| 131 if zone_list: | |
| 132 e['ListHostedZonesResponse']['HostedZones'].extend(zone_list) | |
| 133 while 'NextMarker' in e['ListHostedZonesResponse']: | |
| 134 next_marker = e['ListHostedZonesResponse']['NextMarker'] | |
| 135 zone_list = e['ListHostedZonesResponse']['HostedZones'] | |
| 136 e = self.get_all_hosted_zones(next_marker, zone_list) | |
| 137 return e | |
| 138 | |
| 139 def get_hosted_zone(self, hosted_zone_id): | |
| 140 """ | |
| 141 Get detailed information about a particular Hosted Zone. | |
| 142 | |
| 143 :type hosted_zone_id: str | |
| 144 :param hosted_zone_id: The unique identifier for the Hosted Zone | |
| 145 | |
| 146 """ | |
| 147 uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id) | |
| 148 response = self.make_request('GET', uri) | |
| 149 body = response.read() | |
| 150 boto.log.debug(body) | |
| 151 if response.status >= 300: | |
| 152 raise exception.DNSServerError(response.status, | |
| 153 response.reason, | |
| 154 body) | |
| 155 e = boto.jsonresponse.Element(list_marker='NameServers', | |
| 156 item_marker=('NameServer',)) | |
| 157 h = boto.jsonresponse.XmlHandler(e, None) | |
| 158 h.parse(body) | |
| 159 return e | |
| 160 | |
| 161 def get_hosted_zone_by_name(self, hosted_zone_name): | |
| 162 """ | |
| 163 Get detailed information about a particular Hosted Zone. | |
| 164 | |
| 165 :type hosted_zone_name: str | |
| 166 :param hosted_zone_name: The fully qualified domain name for the Hosted | |
| 167 Zone | |
| 168 | |
| 169 """ | |
| 170 if hosted_zone_name[-1] != '.': | |
| 171 hosted_zone_name += '.' | |
| 172 all_hosted_zones = self.get_all_hosted_zones() | |
| 173 for zone in all_hosted_zones['ListHostedZonesResponse']['HostedZones']: | |
| 174 # check that they gave us the FQDN for their zone | |
| 175 if zone['Name'] == hosted_zone_name: | |
| 176 return self.get_hosted_zone(zone['Id'].split('/')[-1]) | |
| 177 | |
| 178 def create_hosted_zone(self, domain_name, caller_ref=None, comment='', | |
| 179 private_zone=False, vpc_id=None, vpc_region=None): | |
| 180 """ | |
| 181 Create a new Hosted Zone. Returns a Python data structure with | |
| 182 information about the newly created Hosted Zone. | |
| 183 | |
| 184 :type domain_name: str | |
| 185 :param domain_name: The name of the domain. This should be a | |
| 186 fully-specified domain, and should end with a final period | |
| 187 as the last label indication. If you omit the final period, | |
| 188 Amazon Route 53 assumes the domain is relative to the root. | |
| 189 This is the name you have registered with your DNS registrar. | |
| 190 It is also the name you will delegate from your registrar to | |
| 191 the Amazon Route 53 delegation servers returned in | |
| 192 response to this request.A list of strings with the image | |
| 193 IDs wanted. | |
| 194 | |
| 195 :type caller_ref: str | |
| 196 :param caller_ref: A unique string that identifies the request | |
| 197 and that allows failed CreateHostedZone requests to be retried | |
| 198 without the risk of executing the operation twice. If you don't | |
| 199 provide a value for this, boto will generate a Type 4 UUID and | |
| 200 use that. | |
| 201 | |
| 202 :type comment: str | |
| 203 :param comment: Any comments you want to include about the hosted | |
| 204 zone. | |
| 205 | |
| 206 :type private_zone: bool | |
| 207 :param private_zone: Set True if creating a private hosted zone. | |
| 208 | |
| 209 :type vpc_id: str | |
| 210 :param vpc_id: When creating a private hosted zone, the VPC Id to | |
| 211 associate to is required. | |
| 212 | |
| 213 :type vpc_region: str | |
| 214 :param vpc_region: When creating a private hosted zone, the region | |
| 215 of the associated VPC is required. | |
| 216 | |
| 217 """ | |
| 218 if caller_ref is None: | |
| 219 caller_ref = str(uuid.uuid4()) | |
| 220 if private_zone: | |
| 221 params = {'name': domain_name, | |
| 222 'caller_ref': caller_ref, | |
| 223 'comment': comment, | |
| 224 'vpc_id': vpc_id, | |
| 225 'vpc_region': vpc_region, | |
| 226 'xmlns': self.XMLNameSpace} | |
| 227 xml_body = HZPXML % params | |
| 228 else: | |
| 229 params = {'name': domain_name, | |
| 230 'caller_ref': caller_ref, | |
| 231 'comment': comment, | |
| 232 'xmlns': self.XMLNameSpace} | |
| 233 xml_body = HZXML % params | |
| 234 uri = '/%s/hostedzone' % self.Version | |
| 235 response = self.make_request('POST', uri, | |
| 236 {'Content-Type': 'text/xml'}, xml_body) | |
| 237 body = response.read() | |
| 238 boto.log.debug(body) | |
| 239 if response.status == 201: | |
| 240 e = boto.jsonresponse.Element(list_marker='NameServers', | |
| 241 item_marker=('NameServer',)) | |
| 242 h = boto.jsonresponse.XmlHandler(e, None) | |
| 243 h.parse(body) | |
| 244 return e | |
| 245 else: | |
| 246 raise exception.DNSServerError(response.status, | |
| 247 response.reason, | |
| 248 body) | |
| 249 | |
| 250 def delete_hosted_zone(self, hosted_zone_id): | |
| 251 """ | |
| 252 Delete the hosted zone specified by the given id. | |
| 253 | |
| 254 :type hosted_zone_id: str | |
| 255 :param hosted_zone_id: The hosted zone's id | |
| 256 | |
| 257 """ | |
| 258 uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id) | |
| 259 response = self.make_request('DELETE', uri) | |
| 260 body = response.read() | |
| 261 boto.log.debug(body) | |
| 262 if response.status not in (200, 204): | |
| 263 raise exception.DNSServerError(response.status, | |
| 264 response.reason, | |
| 265 body) | |
| 266 e = boto.jsonresponse.Element() | |
| 267 h = boto.jsonresponse.XmlHandler(e, None) | |
| 268 h.parse(body) | |
| 269 return e | |
| 270 | |
| 271 # Health checks | |
| 272 | |
| 273 POSTHCXMLBody = """<CreateHealthCheckRequest xmlns="%(xmlns)s"> | |
| 274 <CallerReference>%(caller_ref)s</CallerReference> | |
| 275 %(health_check)s | |
| 276 </CreateHealthCheckRequest>""" | |
| 277 | |
| 278 def create_health_check(self, health_check, caller_ref=None): | |
| 279 """ | |
| 280 Create a new Health Check | |
| 281 | |
| 282 :type health_check: HealthCheck | |
| 283 :param health_check: HealthCheck object | |
| 284 | |
| 285 :type caller_ref: str | |
| 286 :param caller_ref: A unique string that identifies the request | |
| 287 and that allows failed CreateHealthCheckRequest requests to be retried | |
| 288 without the risk of executing the operation twice. If you don't | |
| 289 provide a value for this, boto will generate a Type 4 UUID and | |
| 290 use that. | |
| 291 | |
| 292 """ | |
| 293 if caller_ref is None: | |
| 294 caller_ref = str(uuid.uuid4()) | |
| 295 uri = '/%s/healthcheck' % self.Version | |
| 296 params = {'xmlns': self.XMLNameSpace, | |
| 297 'caller_ref': caller_ref, | |
| 298 'health_check': health_check.to_xml() | |
| 299 } | |
| 300 xml_body = self.POSTHCXMLBody % params | |
| 301 response = self.make_request('POST', uri, {'Content-Type': 'text/xml'}, xml_body) | |
| 302 body = response.read() | |
| 303 boto.log.debug(body) | |
| 304 if response.status == 201: | |
| 305 e = boto.jsonresponse.Element() | |
| 306 h = boto.jsonresponse.XmlHandler(e, None) | |
| 307 h.parse(body) | |
| 308 return e | |
| 309 else: | |
| 310 raise exception.DNSServerError(response.status, response.reason, body) | |
| 311 | |
| 312 def get_list_health_checks(self, maxitems=None, marker=None): | |
| 313 """ | |
| 314 Return a list of health checks | |
| 315 | |
| 316 :type maxitems: int | |
| 317 :param maxitems: Maximum number of items to return | |
| 318 | |
| 319 :type marker: str | |
| 320 :param marker: marker to get next set of items to list | |
| 321 | |
| 322 """ | |
| 323 | |
| 324 params = {} | |
| 325 if maxitems is not None: | |
| 326 params['maxitems'] = maxitems | |
| 327 if marker is not None: | |
| 328 params['marker'] = marker | |
| 329 | |
| 330 uri = '/%s/healthcheck' % (self.Version, ) | |
| 331 response = self.make_request('GET', uri, params=params) | |
| 332 body = response.read() | |
| 333 boto.log.debug(body) | |
| 334 if response.status >= 300: | |
| 335 raise exception.DNSServerError(response.status, | |
| 336 response.reason, | |
| 337 body) | |
| 338 e = boto.jsonresponse.Element(list_marker='HealthChecks', | |
| 339 item_marker=('HealthCheck',)) | |
| 340 h = boto.jsonresponse.XmlHandler(e, None) | |
| 341 h.parse(body) | |
| 342 return e | |
| 343 | |
| 344 def get_checker_ip_ranges(self): | |
| 345 """ | |
| 346 Return a list of Route53 healthcheck IP ranges | |
| 347 """ | |
| 348 uri = '/%s/checkeripranges' % self.Version | |
| 349 response = self.make_request('GET', uri) | |
| 350 body = response.read() | |
| 351 boto.log.debug(body) | |
| 352 if response.status >= 300: | |
| 353 raise exception.DNSServerError(response.status, | |
| 354 response.reason, | |
| 355 body) | |
| 356 e = boto.jsonresponse.Element(list_marker='CheckerIpRanges', item_marker=('member',)) | |
| 357 h = boto.jsonresponse.XmlHandler(e, None) | |
| 358 h.parse(body) | |
| 359 return e | |
| 360 | |
| 361 def delete_health_check(self, health_check_id): | |
| 362 """ | |
| 363 Delete a health check | |
| 364 | |
| 365 :type health_check_id: str | |
| 366 :param health_check_id: ID of the health check to delete | |
| 367 | |
| 368 """ | |
| 369 uri = '/%s/healthcheck/%s' % (self.Version, health_check_id) | |
| 370 response = self.make_request('DELETE', uri) | |
| 371 body = response.read() | |
| 372 boto.log.debug(body) | |
| 373 if response.status not in (200, 204): | |
| 374 raise exception.DNSServerError(response.status, | |
| 375 response.reason, | |
| 376 body) | |
| 377 e = boto.jsonresponse.Element() | |
| 378 h = boto.jsonresponse.XmlHandler(e, None) | |
| 379 h.parse(body) | |
| 380 return e | |
| 381 | |
| 382 # Resource Record Sets | |
| 383 | |
| 384 def get_all_rrsets(self, hosted_zone_id, type=None, | |
| 385 name=None, identifier=None, maxitems=None): | |
| 386 """ | |
| 387 Retrieve the Resource Record Sets defined for this Hosted Zone. | |
| 388 Returns the raw XML data returned by the Route53 call. | |
| 389 | |
| 390 :type hosted_zone_id: str | |
| 391 :param hosted_zone_id: The unique identifier for the Hosted Zone | |
| 392 | |
| 393 :type type: str | |
| 394 :param type: The type of resource record set to begin the record | |
| 395 listing from. Valid choices are: | |
| 396 | |
| 397 * A | |
| 398 * AAAA | |
| 399 * CNAME | |
| 400 * MX | |
| 401 * NS | |
| 402 * PTR | |
| 403 * SOA | |
| 404 * SPF | |
| 405 * SRV | |
| 406 * TXT | |
| 407 | |
| 408 Valid values for weighted resource record sets: | |
| 409 | |
| 410 * A | |
| 411 * AAAA | |
| 412 * CNAME | |
| 413 * TXT | |
| 414 | |
| 415 Valid values for Zone Apex Aliases: | |
| 416 | |
| 417 * A | |
| 418 * AAAA | |
| 419 | |
| 420 :type name: str | |
| 421 :param name: The first name in the lexicographic ordering of domain | |
| 422 names to be retrieved | |
| 423 | |
| 424 :type identifier: str | |
| 425 :param identifier: In a hosted zone that includes weighted resource | |
| 426 record sets (multiple resource record sets with the same DNS | |
| 427 name and type that are differentiated only by SetIdentifier), | |
| 428 if results were truncated for a given DNS name and type, | |
| 429 the value of SetIdentifier for the next resource record | |
| 430 set that has the current DNS name and type | |
| 431 | |
| 432 :type maxitems: int | |
| 433 :param maxitems: The maximum number of records | |
| 434 | |
| 435 """ | |
| 436 params = {'type': type, 'name': name, | |
| 437 'identifier': identifier, 'maxitems': maxitems} | |
| 438 uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) | |
| 439 response = self.make_request('GET', uri, params=params) | |
| 440 body = response.read() | |
| 441 boto.log.debug(body) | |
| 442 if response.status >= 300: | |
| 443 raise exception.DNSServerError(response.status, | |
| 444 response.reason, | |
| 445 body) | |
| 446 rs = ResourceRecordSets(connection=self, hosted_zone_id=hosted_zone_id) | |
| 447 h = handler.XmlHandler(rs, self) | |
| 448 xml.sax.parseString(body, h) | |
| 449 return rs | |
| 450 | |
| 451 def change_rrsets(self, hosted_zone_id, xml_body): | |
| 452 """ | |
| 453 Create or change the authoritative DNS information for this | |
| 454 Hosted Zone. | |
| 455 Returns a Python data structure with information about the set of | |
| 456 changes, including the Change ID. | |
| 457 | |
| 458 :type hosted_zone_id: str | |
| 459 :param hosted_zone_id: The unique identifier for the Hosted Zone | |
| 460 | |
| 461 :type xml_body: str | |
| 462 :param xml_body: The list of changes to be made, defined in the | |
| 463 XML schema defined by the Route53 service. | |
| 464 | |
| 465 """ | |
| 466 uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) | |
| 467 response = self.make_request('POST', uri, | |
| 468 {'Content-Type': 'text/xml'}, | |
| 469 xml_body) | |
| 470 body = response.read() | |
| 471 boto.log.debug(body) | |
| 472 if response.status >= 300: | |
| 473 raise exception.DNSServerError(response.status, | |
| 474 response.reason, | |
| 475 body) | |
| 476 e = boto.jsonresponse.Element() | |
| 477 h = boto.jsonresponse.XmlHandler(e, None) | |
| 478 h.parse(body) | |
| 479 return e | |
| 480 | |
| 481 def get_change(self, change_id): | |
| 482 """ | |
| 483 Get information about a proposed set of changes, as submitted | |
| 484 by the change_rrsets method. | |
| 485 Returns a Python data structure with status information about the | |
| 486 changes. | |
| 487 | |
| 488 :type change_id: str | |
| 489 :param change_id: The unique identifier for the set of changes. | |
| 490 This ID is returned in the response to the change_rrsets method. | |
| 491 | |
| 492 """ | |
| 493 uri = '/%s/change/%s' % (self.Version, change_id) | |
| 494 response = self.make_request('GET', uri) | |
| 495 body = response.read() | |
| 496 boto.log.debug(body) | |
| 497 if response.status >= 300: | |
| 498 raise exception.DNSServerError(response.status, | |
| 499 response.reason, | |
| 500 body) | |
| 501 e = boto.jsonresponse.Element() | |
| 502 h = boto.jsonresponse.XmlHandler(e, None) | |
| 503 h.parse(body) | |
| 504 return e | |
| 505 | |
| 506 def create_zone(self, name, private_zone=False, | |
| 507 vpc_id=None, vpc_region=None): | |
| 508 """ | |
| 509 Create a new Hosted Zone. Returns a Zone object for the newly | |
| 510 created Hosted Zone. | |
| 511 | |
| 512 :type name: str | |
| 513 :param name: The name of the domain. This should be a | |
| 514 fully-specified domain, and should end with a final period | |
| 515 as the last label indication. If you omit the final period, | |
| 516 Amazon Route 53 assumes the domain is relative to the root. | |
| 517 This is the name you have registered with your DNS registrar. | |
| 518 It is also the name you will delegate from your registrar to | |
| 519 the Amazon Route 53 delegation servers returned in | |
| 520 response to this request. | |
| 521 | |
| 522 :type private_zone: bool | |
| 523 :param private_zone: Set True if creating a private hosted zone. | |
| 524 | |
| 525 :type vpc_id: str | |
| 526 :param vpc_id: When creating a private hosted zone, the VPC Id to | |
| 527 associate to is required. | |
| 528 | |
| 529 :type vpc_region: str | |
| 530 :param vpc_region: When creating a private hosted zone, the region | |
| 531 of the associated VPC is required. | |
| 532 """ | |
| 533 zone = self.create_hosted_zone(name, private_zone=private_zone, | |
| 534 vpc_id=vpc_id, vpc_region=vpc_region) | |
| 535 return Zone(self, zone['CreateHostedZoneResponse']['HostedZone']) | |
| 536 | |
| 537 def get_zone(self, name): | |
| 538 """ | |
| 539 Returns a Zone object for the specified Hosted Zone. | |
| 540 | |
| 541 :param name: The name of the domain. This should be a | |
| 542 fully-specified domain, and should end with a final period | |
| 543 as the last label indication. | |
| 544 """ | |
| 545 name = self._make_qualified(name) | |
| 546 for zone in self.get_zones(): | |
| 547 if name == zone.name: | |
| 548 return zone | |
| 549 | |
| 550 def get_zones(self): | |
| 551 """ | |
| 552 Returns a list of Zone objects, one for each of the Hosted | |
| 553 Zones defined for the AWS account. | |
| 554 | |
| 555 :rtype: list | |
| 556 :returns: A list of Zone objects. | |
| 557 | |
| 558 """ | |
| 559 zones = self.get_all_hosted_zones() | |
| 560 return [Zone(self, zone) for zone in | |
| 561 zones['ListHostedZonesResponse']['HostedZones']] | |
| 562 | |
| 563 def _make_qualified(self, value): | |
| 564 """ | |
| 565 Ensure passed domain names end in a period (.) character. | |
| 566 This will usually make a domain fully qualified. | |
| 567 """ | |
| 568 if type(value) in [list, tuple, set]: | |
| 569 new_list = [] | |
| 570 for record in value: | |
| 571 if record and not record[-1] == '.': | |
| 572 new_list.append("%s." % record) | |
| 573 else: | |
| 574 new_list.append(record) | |
| 575 return new_list | |
| 576 else: | |
| 577 value = value.strip() | |
| 578 if value and not value[-1] == '.': | |
| 579 value = "%s." % value | |
| 580 return value | |
| 581 | |
| 582 def _retry_handler(self, response, i, next_sleep): | |
| 583 status = None | |
| 584 boto.log.debug("Saw HTTP status: %s" % response.status) | |
| 585 | |
| 586 if response.status == 400: | |
| 587 body = response.read() | |
| 588 | |
| 589 # We need to parse the error first | |
| 590 err = exception.DNSServerError( | |
| 591 response.status, | |
| 592 response.reason, | |
| 593 body) | |
| 594 if err.error_code: | |
| 595 # This is a case where we need to ignore a 400 error, as | |
| 596 # Route53 returns this. See | |
| 597 # http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html | |
| 598 if not err.error_code in ( | |
| 599 'PriorRequestNotComplete', | |
| 600 'Throttling', | |
| 601 'ServiceUnavailable', | |
| 602 'RequestExpired'): | |
| 603 return status | |
| 604 msg = "%s, retry attempt %s" % ( | |
| 605 err.error_code, | |
| 606 i | |
| 607 ) | |
| 608 next_sleep = min(random.random() * (2 ** i), | |
| 609 boto.config.get('Boto', 'max_retry_delay', 60)) | |
| 610 i += 1 | |
| 611 status = (msg, i, next_sleep) | |
| 612 | |
| 613 return status |
