OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Author: Chris Moyer |
| 3 # |
| 4 # route53 is similar to sdbadmin for Route53, it's a simple |
| 5 # console utility to perform the most frequent tasks with Route53 |
| 6 # |
| 7 # Example usage. Use route53 get after each command to see how the |
| 8 # zone changes. |
| 9 # |
| 10 # Add a non-weighted record, change its value, then delete. Default TTL: |
| 11 # |
| 12 # route53 add_record ZPO9LGHZ43QB9 rr.example.com A 4.3.2.1 |
| 13 # route53 change_record ZPO9LGHZ43QB9 rr.example.com A 9.8.7.6 |
| 14 # route53 del_record ZPO9LGHZ43QB9 rr.example.com A 9.8.7.6 |
| 15 # |
| 16 # Add a weighted record with two different weights. Note that the TTL |
| 17 # must be specified as route53 uses positional parameters rather than |
| 18 # option flags: |
| 19 # |
| 20 # route53 add_record ZPO9LGHZ43QB9 wrr.example.com A 1.2.3.4 600 foo9 10 |
| 21 # route53 add_record ZPO9LGHZ43QB9 wrr.example.com A 4.3.2.1 600 foo8 10 |
| 22 # |
| 23 # route53 change_record ZPO9LGHZ43QB9 wrr.example.com A 9.9.9.9 600 foo8 10 |
| 24 # |
| 25 # route53 del_record ZPO9LGHZ43QB9 wrr.example.com A 1.2.3.4 600 foo9 10 |
| 26 # route53 del_record ZPO9LGHZ43QB9 wrr.example.com A 9.9.9.9 600 foo8 10 |
| 27 # |
| 28 # Add a non-weighted alias, change its value, then delete. Alaises inherit |
| 29 # their TTLs from the backing ELB: |
| 30 # |
| 31 # route53 add_alias ZPO9LGHZ43QB9 alias.example.com A Z3DZXE0Q79N41H lb-12187615
14.us-east-1.elb.amazonaws.com. |
| 32 # route53 change_alias ZPO9LGHZ43QB9 alias.example.com. A Z3DZXE0Q79N41H lb2-121
8761514.us-east-1.elb.amazonaws.com. |
| 33 # route53 delete_alias ZPO9LGHZ43QB9 alias.example.com. A Z3DZXE0Q79N41H lb2-121
8761514.us-east-1.elb.amazonaws.com. |
| 34 |
| 35 def _print_zone_info(zoneinfo): |
| 36 print "="*80 |
| 37 print "| ID: %s" % zoneinfo['Id'].split("/")[-1] |
| 38 print "| Name: %s" % zoneinfo['Name'] |
| 39 print "| Ref: %s" % zoneinfo['CallerReference'] |
| 40 print "="*80 |
| 41 print zoneinfo['Config'] |
| 42 print |
| 43 |
| 44 |
| 45 def create(conn, hostname, caller_reference=None, comment=''): |
| 46 """Create a hosted zone, returning the nameservers""" |
| 47 response = conn.create_hosted_zone(hostname, caller_reference, comment) |
| 48 print "Pending, please add the following Name Servers:" |
| 49 for ns in response.NameServers: |
| 50 print "\t", ns |
| 51 |
| 52 def delete_zone(conn, hosted_zone_id): |
| 53 """Delete a hosted zone by ID""" |
| 54 response = conn.delete_hosted_zone(hosted_zone_id) |
| 55 print response |
| 56 |
| 57 def ls(conn): |
| 58 """List all hosted zones""" |
| 59 response = conn.get_all_hosted_zones() |
| 60 for zoneinfo in response['ListHostedZonesResponse']['HostedZones']: |
| 61 _print_zone_info(zoneinfo) |
| 62 |
| 63 def get(conn, hosted_zone_id, type=None, name=None, maxitems=None): |
| 64 """Get all the records for a single zone""" |
| 65 response = conn.get_all_rrsets(hosted_zone_id, type, name, maxitems=maxitems
) |
| 66 # If a maximum number of items was set, we limit to that number |
| 67 # by turning the response into an actual list (copying it) |
| 68 # instead of allowing it to page |
| 69 if maxitems: |
| 70 response = response[:] |
| 71 print '%-40s %-5s %-20s %s' % ("Name", "Type", "TTL", "Value(s)") |
| 72 for record in response: |
| 73 print '%-40s %-5s %-20s %s' % (record.name, record.type, record.ttl, rec
ord.to_print()) |
| 74 |
| 75 def _add_del(conn, hosted_zone_id, change, name, type, identifier, weight, value
s, ttl, comment): |
| 76 from boto.route53.record import ResourceRecordSets |
| 77 changes = ResourceRecordSets(conn, hosted_zone_id, comment) |
| 78 change = changes.add_change(change, name, type, ttl, |
| 79 identifier=identifier, weight=weight) |
| 80 for value in values.split(','): |
| 81 change.add_value(value) |
| 82 print changes.commit() |
| 83 |
| 84 def _add_del_alias(conn, hosted_zone_id, change, name, type, identifier, weight,
alias_hosted_zone_id, alias_dns_name, comment): |
| 85 from boto.route53.record import ResourceRecordSets |
| 86 changes = ResourceRecordSets(conn, hosted_zone_id, comment) |
| 87 change = changes.add_change(change, name, type, |
| 88 identifier=identifier, weight=weight) |
| 89 change.set_alias(alias_hosted_zone_id, alias_dns_name) |
| 90 print changes.commit() |
| 91 |
| 92 def add_record(conn, hosted_zone_id, name, type, values, ttl=600, |
| 93 identifier=None, weight=None, comment=""): |
| 94 """Add a new record to a zone. identifier and weight are optional.""" |
| 95 _add_del(conn, hosted_zone_id, "CREATE", name, type, identifier, |
| 96 weight, values, ttl, comment) |
| 97 |
| 98 def del_record(conn, hosted_zone_id, name, type, values, ttl=600, |
| 99 identifier=None, weight=None, comment=""): |
| 100 """Delete a record from a zone: name, type, ttl, identifier, and weight must
match.""" |
| 101 _add_del(conn, hosted_zone_id, "DELETE", name, type, identifier, |
| 102 weight, values, ttl, comment) |
| 103 |
| 104 def add_alias(conn, hosted_zone_id, name, type, alias_hosted_zone_id, |
| 105 alias_dns_name, identifier=None, weight=None, comment=""): |
| 106 """Add a new alias to a zone. identifier and weight are optional.""" |
| 107 _add_del_alias(conn, hosted_zone_id, "CREATE", name, type, identifier, |
| 108 weight, alias_hosted_zone_id, alias_dns_name, comment) |
| 109 |
| 110 def del_alias(conn, hosted_zone_id, name, type, alias_hosted_zone_id, |
| 111 alias_dns_name, identifier=None, weight=None, comment=""): |
| 112 """Delete an alias from a zone: name, type, alias_hosted_zone_id, alias_dns_
name, weight and identifier must match.""" |
| 113 _add_del_alias(conn, hosted_zone_id, "DELETE", name, type, identifier, |
| 114 weight, alias_hosted_zone_id, alias_dns_name, comment) |
| 115 |
| 116 def change_record(conn, hosted_zone_id, name, type, newvalues, ttl=600, |
| 117 identifier=None, weight=None, comment=""): |
| 118 """Delete and then add a record to a zone. identifier and weight are option
al.""" |
| 119 from boto.route53.record import ResourceRecordSets |
| 120 changes = ResourceRecordSets(conn, hosted_zone_id, comment) |
| 121 # Assume there are not more than 10 WRRs for a given (name, type) |
| 122 responses = conn.get_all_rrsets(hosted_zone_id, type, name, maxitems=10) |
| 123 for response in responses: |
| 124 if response.name != name or response.type != type: |
| 125 continue |
| 126 if response.identifier != identifier or response.weight != weight: |
| 127 continue |
| 128 change1 = changes.add_change("DELETE", name, type, response.ttl, |
| 129 identifier=response.identifier, |
| 130 weight=response.weight) |
| 131 for old_value in response.resource_records: |
| 132 change1.add_value(old_value) |
| 133 |
| 134 change2 = changes.add_change("CREATE", name, type, ttl, |
| 135 identifier=identifier, weight=weight) |
| 136 for new_value in newvalues.split(','): |
| 137 change2.add_value(new_value) |
| 138 print changes.commit() |
| 139 |
| 140 def change_alias(conn, hosted_zone_id, name, type, new_alias_hosted_zone_id, new
_alias_dns_name, identifier=None, weight=None, comment=""): |
| 141 """Delete and then add an alias to a zone. identifier and weight are option
al.""" |
| 142 from boto.route53.record import ResourceRecordSets |
| 143 changes = ResourceRecordSets(conn, hosted_zone_id, comment) |
| 144 # Assume there are not more than 10 WRRs for a given (name, type) |
| 145 responses = conn.get_all_rrsets(hosted_zone_id, type, name, maxitems=10) |
| 146 for response in responses: |
| 147 if response.name != name or response.type != type: |
| 148 continue |
| 149 if response.identifier != identifier or response.weight != weight: |
| 150 continue |
| 151 change1 = changes.add_change("DELETE", name, type, |
| 152 identifier=response.identifier, |
| 153 weight=response.weight) |
| 154 change1.set_alias(response.alias_hosted_zone_id, response.alias_dns_name
) |
| 155 change2 = changes.add_change("CREATE", name, type, identifier=identifier, we
ight=weight) |
| 156 change2.set_alias(new_alias_hosted_zone_id, new_alias_dns_name) |
| 157 print changes.commit() |
| 158 |
| 159 def help(conn, fnc=None): |
| 160 """Prints this help message""" |
| 161 import inspect |
| 162 self = sys.modules['__main__'] |
| 163 if fnc: |
| 164 try: |
| 165 cmd = getattr(self, fnc) |
| 166 except: |
| 167 cmd = None |
| 168 if not inspect.isfunction(cmd): |
| 169 print "No function named: %s found" % fnc |
| 170 sys.exit(2) |
| 171 (args, varargs, varkw, defaults) = inspect.getargspec(cmd) |
| 172 print cmd.__doc__ |
| 173 print "Usage: %s %s" % (fnc, " ".join([ "[%s]" % a for a in args[1:]])) |
| 174 else: |
| 175 print "Usage: route53 [command]" |
| 176 for cname in dir(self): |
| 177 if not cname.startswith("_"): |
| 178 cmd = getattr(self, cname) |
| 179 if inspect.isfunction(cmd): |
| 180 doc = cmd.__doc__ |
| 181 print "\t%-20s %s" % (cname, doc) |
| 182 sys.exit(1) |
| 183 |
| 184 |
| 185 if __name__ == "__main__": |
| 186 import boto |
| 187 import sys |
| 188 conn = boto.connect_route53() |
| 189 self = sys.modules['__main__'] |
| 190 if len(sys.argv) >= 2: |
| 191 try: |
| 192 cmd = getattr(self, sys.argv[1]) |
| 193 except: |
| 194 cmd = None |
| 195 args = sys.argv[2:] |
| 196 else: |
| 197 cmd = help |
| 198 args = [] |
| 199 if not cmd: |
| 200 cmd = help |
| 201 try: |
| 202 cmd(conn, *args) |
| 203 except TypeError, e: |
| 204 print e |
| 205 help(conn, cmd.__name__) |
OLD | NEW |