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 |