PageRenderTime 48ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/boto-2.5.2/boto/route53/record.py

#
Python | 291 lines | 258 code | 3 blank | 30 comment | 0 complexity | 9fe360118db000fcf066d9187f3fb39e MD5 | raw file
  1. # Copyright (c) 2010 Chris Moyer http://coredumped.org/
  2. # Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
  3. # Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
  4. # All rights reserved.
  5. #
  6. # Permission is hereby granted, free of charge, to any person obtaining a
  7. # copy of this software and associated documentation files (the
  8. # "Software"), to deal in the Software without restriction, including
  9. # without limitation the rights to use, copy, modify, merge, publish, dis-
  10. # tribute, sublicense, and/or sell copies of the Software, and to permit
  11. # persons to whom the Software is furnished to do so, subject to the fol-
  12. # lowing conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included
  15. # in all copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
  19. # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
  20. # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  23. # IN THE SOFTWARE.
  24. RECORD_TYPES = ['A', 'AAAA', 'TXT', 'CNAME', 'MX', 'PTR', 'SRV', 'SPF']
  25. from boto.resultset import ResultSet
  26. class ResourceRecordSets(ResultSet):
  27. """
  28. A list of resource records.
  29. :ivar hosted_zone_id: The ID of the hosted zone.
  30. :ivar comment: A comment that will be stored with the change.
  31. :ivar changes: A list of changes.
  32. """
  33. ChangeResourceRecordSetsBody = """<?xml version="1.0" encoding="UTF-8"?>
  34. <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2012-02-29/">
  35. <ChangeBatch>
  36. <Comment>%(comment)s</Comment>
  37. <Changes>%(changes)s</Changes>
  38. </ChangeBatch>
  39. </ChangeResourceRecordSetsRequest>"""
  40. ChangeXML = """<Change>
  41. <Action>%(action)s</Action>
  42. %(record)s
  43. </Change>"""
  44. def __init__(self, connection=None, hosted_zone_id=None, comment=None):
  45. self.connection = connection
  46. self.hosted_zone_id = hosted_zone_id
  47. self.comment = comment
  48. self.changes = []
  49. self.next_record_name = None
  50. self.next_record_type = None
  51. ResultSet.__init__(self, [('ResourceRecordSet', Record)])
  52. def __repr__(self):
  53. return '<ResourceRecordSets: %s>' % self.hosted_zone_id
  54. def add_change(self, action, name, type, ttl=600,
  55. alias_hosted_zone_id=None, alias_dns_name=None, identifier=None,
  56. weight=None, region=None):
  57. """
  58. Add a change request to the set.
  59. :type action: str
  60. :param action: The action to perform ('CREATE'|'DELETE')
  61. :type name: str
  62. :param name: The name of the domain you want to perform the action on.
  63. :type type: str
  64. :param type: The DNS record type. Valid values are:
  65. * A
  66. * AAAA
  67. * CNAME
  68. * MX
  69. * NS
  70. * PTR
  71. * SOA
  72. * SPF
  73. * SRV
  74. * TXT
  75. :type ttl: int
  76. :param ttl: The resource record cache time to live (TTL), in seconds.
  77. :type alias_hosted_zone_id: str
  78. :param alias_dns_name: *Alias resource record sets only* The value
  79. of the hosted zone ID, CanonicalHostedZoneNameId, for
  80. the LoadBalancer.
  81. :type alias_dns_name: str
  82. :param alias_hosted_zone_id: *Alias resource record sets only*
  83. Information about the domain to which you are redirecting traffic.
  84. :type identifier: str
  85. :param identifier: *Weighted and latency-based resource record sets
  86. only* An identifier that differentiates among multiple resource
  87. record sets that have the same combination of DNS name and type.
  88. :type weight: int
  89. :param weight: *Weighted resource record sets only* Among resource
  90. record sets that have the same combination of DNS name and type,
  91. a value that determines what portion of traffic for the current
  92. resource record set is routed to the associated location
  93. :type region: str
  94. :param region: *Latency-based resource record sets only* Among resource
  95. record sets that have the same combination of DNS name and type,
  96. a value that determines which region this should be associated with
  97. for the latency-based routing
  98. """
  99. change = Record(name, type, ttl,
  100. alias_hosted_zone_id=alias_hosted_zone_id,
  101. alias_dns_name=alias_dns_name, identifier=identifier,
  102. weight=weight, region=None)
  103. self.changes.append([action, change])
  104. return change
  105. def to_xml(self):
  106. """Convert this ResourceRecordSet into XML
  107. to be saved via the ChangeResourceRecordSetsRequest"""
  108. changesXML = ""
  109. for change in self.changes:
  110. changeParams = {"action": change[0], "record": change[1].to_xml()}
  111. changesXML += self.ChangeXML % changeParams
  112. params = {"comment": self.comment, "changes": changesXML}
  113. return self.ChangeResourceRecordSetsBody % params
  114. def commit(self):
  115. """Commit this change"""
  116. if not self.connection:
  117. import boto
  118. self.connection = boto.connect_route53()
  119. return self.connection.change_rrsets(self.hosted_zone_id, self.to_xml())
  120. def endElement(self, name, value, connection):
  121. """Overwritten to also add the NextRecordName and
  122. NextRecordType to the base object"""
  123. if name == 'NextRecordName':
  124. self.next_record_name = value
  125. elif name == 'NextRecordType':
  126. self.next_record_type = value
  127. else:
  128. return ResultSet.endElement(self, name, value, connection)
  129. def __iter__(self):
  130. """Override the next function to support paging"""
  131. results = ResultSet.__iter__(self)
  132. while results:
  133. for obj in results:
  134. yield obj
  135. if self.is_truncated:
  136. self.is_truncated = False
  137. results = self.connection.get_all_rrsets(self.hosted_zone_id, name=self.next_record_name, type=self.next_record_type)
  138. else:
  139. results = None
  140. class Record(object):
  141. """An individual ResourceRecordSet"""
  142. XMLBody = """<ResourceRecordSet>
  143. <Name>%(name)s</Name>
  144. <Type>%(type)s</Type>
  145. %(weight)s
  146. %(body)s
  147. </ResourceRecordSet>"""
  148. WRRBody = """
  149. <SetIdentifier>%(identifier)s</SetIdentifier>
  150. <Weight>%(weight)s</Weight>
  151. """
  152. RRRBody = """
  153. <SetIdentifier>%(identifier)s</SetIdentifier>
  154. <Region>%(region)s</Region>
  155. """
  156. ResourceRecordsBody = """
  157. <TTL>%(ttl)s</TTL>
  158. <ResourceRecords>
  159. %(records)s
  160. </ResourceRecords>"""
  161. ResourceRecordBody = """<ResourceRecord>
  162. <Value>%s</Value>
  163. </ResourceRecord>"""
  164. AliasBody = """<AliasTarget>
  165. <HostedZoneId>%s</HostedZoneId>
  166. <DNSName>%s</DNSName>
  167. </AliasTarget>"""
  168. def __init__(self, name=None, type=None, ttl=600, resource_records=None,
  169. alias_hosted_zone_id=None, alias_dns_name=None, identifier=None,
  170. weight=None, region=None):
  171. self.name = name
  172. self.type = type
  173. self.ttl = ttl
  174. if resource_records == None:
  175. resource_records = []
  176. self.resource_records = resource_records
  177. self.alias_hosted_zone_id = alias_hosted_zone_id
  178. self.alias_dns_name = alias_dns_name
  179. self.identifier = identifier
  180. self.weight = weight
  181. self.region = region
  182. def add_value(self, value):
  183. """Add a resource record value"""
  184. self.resource_records.append(value)
  185. def set_alias(self, alias_hosted_zone_id, alias_dns_name):
  186. """Make this an alias resource record set"""
  187. self.alias_hosted_zone_id = alias_hosted_zone_id
  188. self.alias_dns_name = alias_dns_name
  189. def to_xml(self):
  190. """Spit this resource record set out as XML"""
  191. if self.alias_hosted_zone_id != None and self.alias_dns_name != None:
  192. # Use alias
  193. body = self.AliasBody % (self.alias_hosted_zone_id, self.alias_dns_name)
  194. else:
  195. # Use resource record(s)
  196. records = ""
  197. for r in self.resource_records:
  198. records += self.ResourceRecordBody % r
  199. body = self.ResourceRecordsBody % {
  200. "ttl": self.ttl,
  201. "records": records,
  202. }
  203. weight = ""
  204. if self.identifier != None and self.weight != None:
  205. weight = self.WRRBody % {"identifier": self.identifier, "weight":
  206. self.weight}
  207. elif self.identifier != None and self.region != None:
  208. weight = self.RRRBody % {"identifier": self.identifier, "region":
  209. self.region}
  210. params = {
  211. "name": self.name,
  212. "type": self.type,
  213. "weight": weight,
  214. "body": body,
  215. }
  216. return self.XMLBody % params
  217. def to_print(self):
  218. rr = ""
  219. if self.alias_hosted_zone_id != None and self.alias_dns_name != None:
  220. # Show alias
  221. rr = 'ALIAS ' + self.alias_hosted_zone_id + ' ' + self.alias_dns_name
  222. else:
  223. # Show resource record(s)
  224. rr = ",".join(self.resource_records)
  225. if self.identifier != None and self.weight != None:
  226. rr += ' (WRR id=%s, w=%s)' % (self.identifier, self.weight)
  227. return rr
  228. def endElement(self, name, value, connection):
  229. if name == 'Name':
  230. self.name = value
  231. elif name == 'Type':
  232. self.type = value
  233. elif name == 'TTL':
  234. self.ttl = value
  235. elif name == 'Value':
  236. self.resource_records.append(value)
  237. elif name == 'HostedZoneId':
  238. self.alias_hosted_zone_id = value
  239. elif name == 'DNSName':
  240. self.alias_dns_name = value
  241. elif name == 'SetIdentifier':
  242. self.identifier = value
  243. elif name == 'Weight':
  244. self.weight = value
  245. elif name == 'Region':
  246. self.region = value
  247. def startElement(self, name, attrs, connection):
  248. return None