diff options
Diffstat (limited to 'roles/lib_dyn')
-rw-r--r-- | roles/lib_dyn/README.md | 27 | ||||
-rw-r--r-- | roles/lib_dyn/library/dyn_record.py | 351 | ||||
-rw-r--r-- | roles/lib_dyn/meta/main.yml | 33 | ||||
-rw-r--r-- | roles/lib_dyn/tasks/main.yml | 7 |
4 files changed, 0 insertions, 418 deletions
diff --git a/roles/lib_dyn/README.md b/roles/lib_dyn/README.md deleted file mode 100644 index 1eec9f81c..000000000 --- a/roles/lib_dyn/README.md +++ /dev/null @@ -1,27 +0,0 @@ -lib_dyn -========= - -A role containing the dyn_record module for managing DNS records through Dyn's -API - -Requirements ------------- - -The module requires the `dyn` python module for interacting with the Dyn API. -https://github.com/dyninc/dyn-python - -Example Playbook ----------------- - -To make sure the `dyn_record` module is available for use include the role -before it is used. - - - hosts: servers - roles: - - lib_dyn - -License -------- - -Apache - diff --git a/roles/lib_dyn/library/dyn_record.py b/roles/lib_dyn/library/dyn_record.py deleted file mode 100644 index 42d970060..000000000 --- a/roles/lib_dyn/library/dyn_record.py +++ /dev/null @@ -1,351 +0,0 @@ -#!/usr/bin/python -# -# (c) 2015, Russell Harrison <rharriso@redhat.com> -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# pylint: disable=too-many-branches -'''Ansible module to manage records in the Dyn Managed DNS service''' -DOCUMENTATION = ''' ---- -module: dyn_record -version_added: "1.9" -short_description: Manage records in the Dyn Managed DNS service. -description: - - "Manages DNS records via the REST API of the Dyn Managed DNS service. It - - "handles records only; there is no manipulation of zones or account support" - - "yet. See: U(https://help.dyn.com/dns-api-knowledge-base/)" -options: - state: - description: - -"Whether the record should be c(present) or c(absent). Optionally the" - - "state c(list) can be used to return the current value of a record." - required: true - choices: [ 'present', 'absent', 'list' ] - default: present - - customer_name: - description: - - "The Dyn customer name for your account. If not set the value of the" - - "c(DYNECT_CUSTOMER_NAME) environment variable is used." - required: false - default: nil - - user_name: - description: - - "The Dyn user name to log in with. If not set the value of the" - - "c(DYNECT_USER_NAME) environment variable is used." - required: false - default: null - - user_password: - description: - - "The Dyn user's password to log in with. If not set the value of the" - - "c(DYNECT_PASSWORD) environment variable is used." - required: false - default: null - - zone: - description: - - "The DNS zone in which your record is located." - required: true - default: null - - record_fqdn: - description: - - "Fully qualified domain name of the record name to get, create, delete," - - "or update." - required: true - default: null - - record_type: - description: - - "Record type." - required: true - choices: [ 'A', 'AAAA', 'CNAME', 'PTR', 'TXT' ] - default: null - - record_value: - description: - - "Record value. If record_value is not specified; no changes will be" - - "made and the module will fail" - required: false - default: null - - record_ttl: - description: - - 'Record's "Time to live". Number of seconds the record remains cached' - - 'in DNS servers or c(0) to use the default TTL for the zone.' - - 'This option is mutually exclusive with use_zone_ttl' - required: false - default: 0 - - use_zone_ttl: - description: - - 'Use the DYN Zone's Default TTL' - - 'This option is mutually exclusive with record_ttl' - required: false - default: false - mutually exclusive with: record_ttl - -notes: - - The module makes a broad assumption that there will be only one record per "node" (FQDN). - - This module returns record(s) in the "result" element when 'state' is set to 'present'. This value can be be registered and used in your playbooks. - -requirements: [ dyn ] -author: "Russell Harrison" -''' - -EXAMPLES = ''' -# Attempting to cname www.example.com to web1.example.com -- name: Update CNAME record - dyn_record: - state: present - record_fqdn: www.example.com - zone: example.com - record_type: CNAME - record_value: web1.example.com - record_ttl: 7200 - -# Use the zones default TTL -- name: Update CNAME record - dyn_record: - state: present - record_fqdn: www.example.com - zone: example.com - record_type: CNAME - record_value: web1.example.com - use_zone_ttl: true - -- name: Update A record - dyn_record: - state: present - record_fqdn: web1.example.com - zone: example.com - record_value: 10.0.0.10 - record_type: A -''' - -try: - IMPORT_ERROR = False - from dyn.tm.session import DynectSession - from dyn.tm.zones import Zone - import dyn.tm.errors - import os - -except ImportError as error: - IMPORT_ERROR = str(error) - -# Each of the record types use a different method for the value. -RECORD_PARAMS = { - 'A' : {'value_param': 'address'}, - 'AAAA' : {'value_param': 'address'}, - 'CNAME' : {'value_param': 'cname'}, - 'PTR' : {'value_param': 'ptrdname'}, - 'TXT' : {'value_param': 'txtdata'} -} - -# You'll notice that the value_param doesn't match the key (records_key) -# in the dict returned from Dyn when doing a dyn_node.get_all_records() -# This is a frustrating lookup dict to allow mapping to the RECORD_PARAMS -# dict so we can lookup other values in it efficiently - -def get_record_type(record_key): - '''Get the record type represented by the keys returned from get_any_records.''' - return record_key.replace('_records', '').upper() - -def get_record_key(record_type): - '''Get the key to look up records in the dictionary returned from get_any_records. - example: - 'cname_records' - ''' - return record_type.lower() + '_records' - -def get_any_records(module, node): - '''Get any records for a given node''' - # Lets get a list of the A records for the node - try: - records = node.get_any_records() - except dyn.tm.errors.DynectGetError as error: - if 'Not in zone' in str(error): - # The node isn't in the zone so we'll return an empty dictionary - return {} - else: - # An unknown error happened so we'll need to return it. - module.fail_json(msg='Unable to get records', - error=str(error)) - - # Return a dictionary of the record objects - return records - -def get_record_values(records): - '''Get the record values for each record returned by get_any_records.''' - # This simply returns the values from a record - ret_dict = {} - for key in records.keys(): - record_type = get_record_type(key) - params = [RECORD_PARAMS[record_type]['value_param'], 'ttl', 'zone', 'fqdn'] - ret_dict[key] = [] - properties = {} - for elem in records[key]: - for param in params: - properties[param] = getattr(elem, param) - ret_dict[key].append(properties) - - return ret_dict - -def compare_record_values(record_type_key, user_record_value, dyn_values): - ''' Verify the user record_value exists in dyn''' - rtype = get_record_type(record_type_key) - for record in dyn_values[record_type_key]: - if user_record_value in record[RECORD_PARAMS[rtype]['value_param']]: - return True - - return False - -def compare_record_ttl(record_type_key, user_record_value, dyn_values, user_param_ttl): - ''' Verify the ttls match for the record''' - rtype = get_record_type(record_type_key) - for record in dyn_values[record_type_key]: - # find the right record - if user_record_value in record[RECORD_PARAMS[rtype]['value_param']]: - # Compare ttls from the records - if int(record['ttl']) == user_param_ttl: - return True - - return False - -def main(): - '''Ansible module for managing Dyn DNS records.''' - module = AnsibleModule( - argument_spec=dict( - state=dict(default='present', choices=['present', 'absent', 'list']), - customer_name=dict(default=os.environ.get('DYNECT_CUSTOMER_NAME', None), type='str'), - user_name=dict(default=os.environ.get('DYNECT_USER_NAME', None), type='str', no_log=True), - user_password=dict(default=os.environ.get('DYNECT_PASSWORD', None), type='str', no_log=True), - zone=dict(required=True, type='str'), - record_fqdn=dict(required=False, type='str'), - record_type=dict(required=False, type='str', choices=[ - 'A', 'AAAA', 'CNAME', 'PTR', 'TXT']), - record_value=dict(required=False, type='str'), - record_ttl=dict(required=False, default=None, type='int'), - use_zone_ttl=dict(required=False, default=False), - ), - required_together=( - ['record_fqdn', 'record_value', 'record_ttl', 'record_type'] - ), - mutually_exclusive=[('record_ttl', 'use_zone_ttl')] - ) - - if IMPORT_ERROR: - module.fail_json(msg="Unable to import dyn module: https://pypi.python.org/pypi/dyn", error=IMPORT_ERROR) - - if module.params['record_ttl'] != None and int(module.params['record_ttl']) <= 0: - module.fail_json(msg="Invalid Value for record TTL") - - # Start the Dyn session - try: - _ = DynectSession(module.params['customer_name'], - module.params['user_name'], - module.params['user_password']) - except dyn.tm.errors.DynectAuthError as error: - module.fail_json(msg='Unable to authenticate with Dyn', error=str(error)) - - # Retrieve zone object - try: - dyn_zone = Zone(module.params['zone']) - except dyn.tm.errors.DynectGetError as error: - if 'No such zone' in str(error): - module.fail_json(msg="Not a valid zone for this account", zone=module.params['zone']) - else: - module.fail_json(msg="Unable to retrieve zone", error=str(error)) - - # To retrieve the node object we need to remove the zone name from the FQDN - dyn_node_name = module.params['record_fqdn'].replace('.' + module.params['zone'], '') - - # Retrieve the zone object from dyn - dyn_zone = Zone(module.params['zone']) - - # Retrieve the node object from dyn - dyn_node = dyn_zone.get_node(node=dyn_node_name) - - # All states will need a list of the exiting records for the zone. - dyn_node_records = get_any_records(module, dyn_node) - - dyn_values = get_record_values(dyn_node_records) - - if module.params['state'] == 'list': - module.exit_json(changed=False, dyn_records=dyn_values) - - elif module.params['state'] == 'absent': - # If there are any records present we'll want to delete the node. - if dyn_node_records: - dyn_node.delete() - - # Publish the zone since we've modified it. - dyn_zone.publish() - - module.exit_json(changed=True, msg="Removed node %s from zone %s" % (dyn_node_name, module.params['zone'])) - - module.exit_json(changed=False) - - elif module.params['state'] == 'present': - - # configure the TTL variable: - # if use_zone_ttl, use the default TTL of the account. - # if TTL == None, don't check it, set it as 0 (api default) - # if TTL > 0, ensure this TTL is set - if module.params['use_zone_ttl']: - user_param_ttl = dyn_zone.ttl - elif not module.params['record_ttl']: - user_param_ttl = 0 - else: - user_param_ttl = module.params['record_ttl'] - - # First get a list of existing records for the node - record_type_key = get_record_key(module.params['record_type']) - user_record_value = module.params['record_value'] - - # Check to see if the record is already in place before doing anything. - if dyn_node_records and compare_record_values(record_type_key, user_record_value, dyn_values): - - if user_param_ttl == 0 or \ - compare_record_ttl(record_type_key, user_record_value, dyn_values, user_param_ttl): - module.exit_json(changed=False, dyn_record=dyn_values) - - # Working on the assumption that there is only one record per - # node we will first delete the node if there are any records before - # creating the correct record - if dyn_node_records: - dyn_node.delete() - - # Now lets create the correct node entry. - record = dyn_zone.add_record(dyn_node_name, - module.params['record_type'], - module.params['record_value'], - user_param_ttl - ) - - # Now publish the zone since we've updated it. - dyn_zone.publish() - - rmsg = "Created node [%s] " % dyn_node_name - rmsg += "in zone: [%s]" % module.params['zone'] - module.exit_json(changed=True, msg=rmsg, dyn_record=get_record_values({record_type_key: [record]})) - - module.fail_json(msg="Unknown state: [%s]" % module.params['state']) - -# Ansible tends to need a wild card import so we'll use it here -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -from ansible.module_utils.basic import * -if __name__ == '__main__': - main() diff --git a/roles/lib_dyn/meta/main.yml b/roles/lib_dyn/meta/main.yml deleted file mode 100644 index 5475c6971..000000000 --- a/roles/lib_dyn/meta/main.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -galaxy_info: - author: Russell Harrison - description: A role to provide the dyn_record module - company: Red Hat, Inc. - # If the issue tracker for your role is not on github, uncomment the - # next line and provide a value - # issue_tracker_url: http://example.com/issue/tracker - license: Apache - min_ansible_version: 1.9 - platforms: - - name: EL - versions: - - 7 - #- name: Fedora - # versions: - # - 19 - # - 20 - # - 21 - # - 22 - # Below are all categories currently available. Just as with - # the platforms above, uncomment those that apply to your role. - categories: - - networking -dependencies: [] - # List your role dependencies here, one per line. - # Be sure to remove the '[]' above if you add dependencies - # to this list. - # - # No role dependencies at this time. The module contained in this role does - # require the dyn python module. - # https://pypi.python.org/pypi/dyn - diff --git a/roles/lib_dyn/tasks/main.yml b/roles/lib_dyn/tasks/main.yml deleted file mode 100644 index 965962928..000000000 --- a/roles/lib_dyn/tasks/main.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -# tasks file for lib_dyn - -- name: Make sure python-dyn is installed - yum: name=python-dyn state=present - tags: - - lib_dyn |