| OLD | NEW |
| 1 # Copyright (c) 2010 Chris Moyer http://coredumped.org/ | 1 # Copyright (c) 2010 Chris Moyer http://coredumped.org/ |
| 2 # All rights reserved. | 2 # All rights reserved. |
| 3 # | 3 # |
| 4 # Permission is hereby granted, free of charge, to any person obtaining a | 4 # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 # copy of this software and associated documentation files (the | 5 # copy of this software and associated documentation files (the |
| 6 # "Software"), to deal in the Software without restriction, including | 6 # "Software"), to deal in the Software without restriction, including |
| 7 # without limitation the rights to use, copy, modify, merge, publish, dis- | 7 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 8 # tribute, sublicense, and/or sell copies of the Software, and to permit | 8 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 9 # persons to whom the Software is furnished to do so, subject to the fol- | 9 # persons to whom the Software is furnished to do so, subject to the fol- |
| 10 # lowing conditions: | 10 # lowing conditions: |
| 11 # | 11 # |
| 12 # The above copyright notice and this permission notice shall be included | 12 # The above copyright notice and this permission notice shall be included |
| 13 # in all copies or substantial portions of the Software. | 13 # in all copies or substantial portions of the Software. |
| 14 # | 14 # |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
| 17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | 17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
| 18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | 18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 21 # IN THE SOFTWARE. | 21 # IN THE SOFTWARE. |
| 22 | 22 |
| 23 RECORD_TYPES = ['A', 'AAAA', 'TXT', 'CNAME', 'MX', 'PTR', 'SRV', 'SPF'] | 23 RECORD_TYPES = ['A', 'AAAA', 'TXT', 'CNAME', 'MX', 'PTR', 'SRV', 'SPF'] |
| 24 | 24 |
| 25 from boto.resultset import ResultSet | 25 from boto.resultset import ResultSet |
| 26 class ResourceRecordSets(ResultSet): | 26 class ResourceRecordSets(ResultSet): |
| 27 | 27 |
| 28 ChangeResourceRecordSetsBody = """<?xml version="1.0" encoding="UTF-8"?> | 28 ChangeResourceRecordSetsBody = """<?xml version="1.0" encoding="UTF-8"?> |
| 29 <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/20
10-10-01/"> | 29 <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/20
11-05-05/"> |
| 30 <ChangeBatch> | 30 <ChangeBatch> |
| 31 <Comment>%(comment)s</Comment> | 31 <Comment>%(comment)s</Comment> |
| 32 <Changes>%(changes)s</Changes> | 32 <Changes>%(changes)s</Changes> |
| 33 </ChangeBatch> | 33 </ChangeBatch> |
| 34 </ChangeResourceRecordSetsRequest>""" | 34 </ChangeResourceRecordSetsRequest>""" |
| 35 | 35 |
| 36 ChangeXML = """<Change> | 36 ChangeXML = """<Change> |
| 37 <Action>%(action)s</Action> | 37 <Action>%(action)s</Action> |
| 38 %(record)s | 38 %(record)s |
| 39 </Change>""" | 39 </Change>""" |
| 40 | 40 |
| 41 | 41 |
| 42 def __init__(self, connection=None, hosted_zone_id=None, comment=None): | 42 def __init__(self, connection=None, hosted_zone_id=None, comment=None): |
| 43 self.connection = connection | 43 self.connection = connection |
| 44 self.hosted_zone_id = hosted_zone_id | 44 self.hosted_zone_id = hosted_zone_id |
| 45 self.comment = comment | 45 self.comment = comment |
| 46 self.changes = [] | 46 self.changes = [] |
| 47 self.next_record_name = None | 47 self.next_record_name = None |
| 48 self.next_record_type = None | 48 self.next_record_type = None |
| 49 ResultSet.__init__(self, [('ResourceRecordSet', Record)]) | 49 ResultSet.__init__(self, [('ResourceRecordSet', Record)]) |
| 50 | 50 |
| 51 def __repr__(self): | 51 def __repr__(self): |
| 52 return '<ResourceRecordSets: %s>' % self.hosted_zone_id | 52 return '<ResourceRecordSets: %s>' % self.hosted_zone_id |
| 53 | 53 |
| 54 def add_change(self, action, name, type, ttl=600): | 54 def add_change(self, action, name, type, ttl=600, alias_hosted_zone_id=None,
alias_dns_name=None): |
| 55 """Add a change request""" | 55 """Add a change request""" |
| 56 change = Record(name, type, ttl) | 56 change = Record(name, type, ttl, alias_hosted_zone_id=alias_hosted_zone_
id, alias_dns_name=alias_dns_name) |
| 57 self.changes.append([action, change]) | 57 self.changes.append([action, change]) |
| 58 return change | 58 return change |
| 59 | 59 |
| 60 def to_xml(self): | 60 def to_xml(self): |
| 61 """Convert this ResourceRecordSet into XML | 61 """Convert this ResourceRecordSet into XML |
| 62 to be saved via the ChangeResourceRecordSetsRequest""" | 62 to be saved via the ChangeResourceRecordSetsRequest""" |
| 63 changesXML = "" | 63 changesXML = "" |
| 64 for change in self.changes: | 64 for change in self.changes: |
| 65 changeParams = {"action": change[0], "record": change[1].to_xml()} | 65 changeParams = {"action": change[0], "record": change[1].to_xml()} |
| 66 changesXML += self.ChangeXML % changeParams | 66 changesXML += self.ChangeXML % changeParams |
| (...skipping 30 matching lines...) Expand all Loading... |
| 97 results = None | 97 results = None |
| 98 | 98 |
| 99 | 99 |
| 100 | 100 |
| 101 class Record(object): | 101 class Record(object): |
| 102 """An individual ResourceRecordSet""" | 102 """An individual ResourceRecordSet""" |
| 103 | 103 |
| 104 XMLBody = """<ResourceRecordSet> | 104 XMLBody = """<ResourceRecordSet> |
| 105 <Name>%(name)s</Name> | 105 <Name>%(name)s</Name> |
| 106 <Type>%(type)s</Type> | 106 <Type>%(type)s</Type> |
| 107 %(body)s |
| 108 </ResourceRecordSet>""" |
| 109 |
| 110 ResourceRecordsBody = """ |
| 107 <TTL>%(ttl)s</TTL> | 111 <TTL>%(ttl)s</TTL> |
| 108 <ResourceRecords>%(records)s</ResourceRecords> | 112 <ResourceRecords> |
| 109 </ResourceRecordSet>""" | 113 %(records)s |
| 114 </ResourceRecords>""" |
| 110 | 115 |
| 111 ResourceRecordBody = """<ResourceRecord> | 116 ResourceRecordBody = """<ResourceRecord> |
| 112 <Value>%s</Value> | 117 <Value>%s</Value> |
| 113 </ResourceRecord>""" | 118 </ResourceRecord>""" |
| 114 | 119 |
| 120 AliasBody = """<AliasTarget> |
| 121 <HostedZoneId>%s</HostedZoneId> |
| 122 <DNSName>%s</DNSName> |
| 123 </AliasTarget>""" |
| 115 | 124 |
| 116 def __init__(self, name=None, type=None, ttl=600, resource_records=None): | 125 def __init__(self, name=None, type=None, ttl=600, resource_records=None, ali
as_hosted_zone_id=None, alias_dns_name=None): |
| 117 self.name = name | 126 self.name = name |
| 118 self.type = type | 127 self.type = type |
| 119 self.ttl = ttl | 128 self.ttl = ttl |
| 120 if resource_records == None: | 129 if resource_records == None: |
| 121 resource_records = [] | 130 resource_records = [] |
| 122 self.resource_records = resource_records | 131 self.resource_records = resource_records |
| 132 self.alias_hosted_zone_id = alias_hosted_zone_id |
| 133 self.alias_dns_name = alias_dns_name |
| 123 | 134 |
| 124 def add_value(self, value): | 135 def add_value(self, value): |
| 125 """Add a resource record value""" | 136 """Add a resource record value""" |
| 126 self.resource_records.append(value) | 137 self.resource_records.append(value) |
| 127 | 138 |
| 139 def set_alias(self, alias_hosted_zone_id, alias_dns_name): |
| 140 """Make this an alias resource record set""" |
| 141 self.alias_hosted_zone_id = alias_hosted_zone_id |
| 142 self.alias_dns_name = alias_dns_name |
| 143 |
| 128 def to_xml(self): | 144 def to_xml(self): |
| 129 """Spit this resource record set out as XML""" | 145 """Spit this resource record set out as XML""" |
| 130 records = "" | 146 if self.alias_hosted_zone_id != None and self.alias_dns_name != None: |
| 131 for r in self.resource_records: | 147 # Use alias |
| 132 records += self.ResourceRecordBody % r | 148 body = self.AliasBody % (self.alias_hosted_zone_id, self.alias_dns_n
ame) |
| 149 else: |
| 150 # Use resource record(s) |
| 151 records = "" |
| 152 for r in self.resource_records: |
| 153 records += self.ResourceRecordBody % r |
| 154 body = self.ResourceRecordsBody % { |
| 155 "ttl": self.ttl, |
| 156 "records": records, |
| 157 } |
| 133 params = { | 158 params = { |
| 134 "name": self.name, | 159 "name": self.name, |
| 135 "type": self.type, | 160 "type": self.type, |
| 136 "ttl": self.ttl, | 161 "body": body, |
| 137 "records": records | |
| 138 } | 162 } |
| 139 return self.XMLBody % params | 163 return self.XMLBody % params |
| 140 | 164 |
| 165 def to_print(self): |
| 166 if self.alias_hosted_zone_id != None and self.alias_dns_name != None: |
| 167 # Show alias |
| 168 return 'ALIAS ' + self.alias_hosted_zone_id + ' ' + self.alias_dns_n
ame |
| 169 else: |
| 170 # Show resource record(s) |
| 171 return ",".join(self.resource_records) |
| 172 |
| 141 def endElement(self, name, value, connection): | 173 def endElement(self, name, value, connection): |
| 142 if name == 'Name': | 174 if name == 'Name': |
| 143 self.name = value | 175 self.name = value |
| 144 elif name == 'Type': | 176 elif name == 'Type': |
| 145 self.type = value | 177 self.type = value |
| 146 elif name == 'TTL': | 178 elif name == 'TTL': |
| 147 self.ttl = value | 179 self.ttl = value |
| 148 elif name == 'Value': | 180 elif name == 'Value': |
| 149 self.resource_records.append(value) | 181 self.resource_records.append(value) |
| 182 elif name == 'HostedZoneId': |
| 183 self.alias_hosted_zone_id = value |
| 184 elif name == 'DNSName': |
| 185 self.alias_dns_name = value |
| 150 | 186 |
| 151 def startElement(self, name, attrs, connection): | 187 def startElement(self, name, attrs, connection): |
| 152 return None | 188 return None |
| OLD | NEW |