Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS route53 module #3574

Merged
merged 3 commits into from
Jul 21, 2013
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
232 changes: 232 additions & 0 deletions library/cloud/route53
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#!/usr/bin/python
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.

DOCUMENTATION = '''
---
module: rds
version_added: "1.4"
short_description: add or delete entries in Amazons Route53 DNS service
description:
- Creates and deletes DNS records in Amazons Route53 service
options:
command:
description:
- Specifies the action to take.
required: true
default: null
aliases: []
choices: [ 'get', 'create', 'delete' ]
zone:
description:
- The DNS zone to modify
required: true
default: null
aliases: []
record:
description:
- The full DNS record to create or delete
required: true
default: null
aliases: []
ttl:
description:
- The TTL to give the new record
required: false
default: 3600 (one hour)
aliases: []
type:
description:
- The type of DNS record to create
required: true
default: null
aliases: []
choices: [ 'A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'NS' ]
value:
description:
- The new value when creating a DNS record. Multiple comma-spaced values are allowed. When deleting a record all values for the record must be specified or Route53 will not delete it.
required: false
default: null
aliases: []
ec2_secret_key:
description:
- EC2 secret key. If not specified then the EC2_SECRET_KEY environment variable is used.
required: false
default: null
aliases: []
ec2_access_key:
description:
- EC2 access key. If not specified then the EC2_ACCESS_KEY environment variable is used.
required: false
default: null
aliases: []
requirements: [ "boto" ]
author: Bruce Pennypacker
'''

EXAMPLES = '''
# Add new.foo.com as an A record with 3 IPs
- route53: >
command=create
zone=foo.com
record=new.foo.com
type=A
ttl=7200
value=1.1.1.1,2.2.2.2,3.3.3.3

# Retrieve the details for new.foo.com
- route53: >
command=get
zone=foo.com
record=new.foo.com
type=A
register: rec

# Delete new.foo.com A record using the results from the get command
- route53: >
command=delete
zone=foo.com
record={{ r.set.record }}
type={{ r.set.type }}
value={{ r.set.value }}

# Add an AAAA record. Note that because there are colons in the value
# that the entire parameter list must be quoted:
- route53: >
"command=create
zone=foo.com
record=localhost.foo.com
type=AAAA
ttl=7200
value=::1"
'''

import sys

try:
import boto
from boto import route53
from boto.route53.record import ResourceRecordSets
except ImportError:
print "failed=True msg='boto required for this module'"
sys.exit(1)

def main():
module = AnsibleModule(
argument_spec = dict(
command = dict(choices=['get', 'create', 'delete'], required=True),
zone = dict(required=True),
record = dict(required=True),
ttl = dict(required=False, default=3600),
type = dict(choices=['A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'NS'], required=True),
value = dict(required=False),
ec2_secret_key = dict(aliases=['EC2_SECRET_KEY'], no_log=True, required=False),
ec2_access_key = dict(aliases=['EC2_ACCESS_KEY'], required=False)
)
)

command_in = module.params.get('command')
zone_in = module.params.get('zone');
ttl_in = module.params.get('ttl');
record_in = module.params.get('record');
type_in = module.params.get('type');
value_in = module.params.get('value');
ec2_secret_key = module.params.get('ec2_secret_key')
ec2_access_key = module.params.get('ec2_access_key')

value_list = ()

if type(value_in) is str:
if value_in:
value_list = sorted(value_in.split(','))
elif type(value_in) is list:
value_list = sorted(value_in)

if zone_in[-1:] != '.':
zone_in += "."

if record_in[-1:] != '.':
record_in += "."

if command_in == 'create' or command_in == 'delete':
if not value_in:
module.fail_json(msg = "parameter 'value' required for create/delete")

# allow environment variables to be used if ansible vars aren't set
if not ec2_secret_key and 'EC2_SECRET_KEY' in os.environ:
ec2_secret_key = os.environ['EC2_SECRET_KEY']
if not ec2_access_key and 'EC2_ACCESS_KEY' in os.environ:
ec2_access_key = os.environ['EC2_ACCESS_KEY']

# connect to the route53 endpoint
try:
conn = boto.route53.connection.Route53Connection(ec2_access_key, ec2_secret_key)
except boto.exception.BotoServerError, e:
module.fail_json(msg = e.error_message)

# Get all the existing hosted zones and save their ID's
zones = {}
results = conn.get_all_hosted_zones()
for r53zone in results['ListHostedZonesResponse']['HostedZones']:
zone_id = r53zone['Id'].replace('/hostedzone/', '')
zones[r53zone['Name']] = zone_id

# Verify that the requested zone is already defined in Route53
if not zone_in in zones:
errmsg = "Zone %s does not exist in Route53" % zone_in
module.fail_json(msg = errmsg)

record = {}

found_record = False
sets = conn.get_all_rrsets(zones[zone_in])
for rset in sets:
if rset.type == type_in and rset.name == record_in:
found_record = True
record['zone'] = zone_in
record['type'] = rset.type
record['record'] = rset.name
record['ttl'] = rset.ttl
record['value'] = ','.join(sorted(rset.resource_records))
record['values'] = sorted(rset.resource_records)
if value_list == sorted(rset.resource_records) and command_in == 'create':
module.exit_json(changed=False)

if command_in == 'get':
module.exit_json(changed=False, set=record)

if command_in == 'delete' and not found_record:
module.exit_json(changed=False)

changes = ResourceRecordSets(conn, zones[zone_in])

if command_in == 'create' or command_in == 'delete':
change = changes.add_change(command_in.upper(), record_in, type_in, ttl_in)
for v in value_list:
change.add_value(v)

try:
result = changes.commit()
except boto.route53.exception.DNSServerError, e:
txt = e.body.split("<Message>")[1]
txt = txt.split("</Message>")[0]
module.fail_json(msg = txt)

module.exit_json(changed=True)

# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>

main()