Last active
June 14, 2023 07:36
-
-
Save jmbwell/ae788a31a9120fe3a5ccf667a4902fe3 to your computer and use it in GitHub Desktop.
A quick Ansible module for updating DreamHost DNS records.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# Copyright: (c) 2022, John Burwell <[email protected]> | |
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | |
from __future__ import (absolute_import, division, print_function) | |
__metaclass__ = type | |
DOCUMENTATION = r''' | |
--- | |
module: dreamhost_dns | |
short_description: Dreamhost DNS API | |
version_added: "0.0.1" | |
description: For adding or removing Dreamhost DNS records. | |
options: | |
api_key: | |
description: The API key from the Dreamhost billing console. | |
required: true | |
type: str | |
comment: | |
description: A comment for the record, as to appear in the Dreamhost console. | |
required: false | |
type: str | |
name: | |
description: This is the message to send to the test module. | |
required: true | |
type: str | |
state: | |
description: | |
- present (default) | |
- absent | |
required: false | |
type: str | |
type: | |
description: | |
- The type of DNS record: A, AAAA, CNAME, TXT, etc. | |
required: true | |
type: str | |
value: | |
description: | |
- The value for the record: the IP address, etc. | |
required: true | |
type: str | |
extends_documentation_fragment: | |
- jmbwell.dreamhost_api.dreamhost_dns | |
author: | |
- John Burwell (@jmbwell) | |
''' | |
EXAMPLES = r''' | |
- name: test.example.com exists | |
jmbwell.dreamhost_api.dreamhost_dns: | |
- name: test.example.com | |
type: A | |
value: 127.0.0.1 | |
comment: "Set by Ansible" | |
api_key=key | |
state: present | |
- name: test.example.com does not exist | |
jmbwell.dreamhost_api.dreamhost_dns: | |
- name: test.example.com | |
type: A | |
value: 127.0.0.1 | |
comment: "Set by Ansible" | |
api_key=key | |
state: absent | |
''' | |
RETURN = r''' | |
response: | |
description: the message returned by the Dreamhost API | |
type: str | |
returned: always | |
sample: "result: success" | |
''' | |
import urllib.request, json | |
from ansible.module_utils.basic import AnsibleModule | |
from ansible.module_utils._text import to_text | |
def call_api(api_key, command, cmd_params=dict()): | |
params = dict( | |
key = api_key, | |
format = "json", | |
cmd = command, | |
**cmd_params | |
) | |
query_string = urllib.parse.urlencode( params ) | |
url = "https://api.dreamhost.com/" + "?" + query_string | |
with urllib.request.urlopen( url ) as response: | |
response_text = response.read() | |
return json.loads(response_text.decode("utf-8")) | |
def list_records(api_key): | |
return call_api(api_key, "dns-list_records") | |
def add_record(api_key, params): | |
return call_api(api_key, "dns-add_record", params) | |
def remove_record(api_key, params): | |
return call_api(api_key, "dns-remove_record", params) | |
def match_record(records, params): | |
for each_record in records['data']: | |
if (each_record['record'] == params['record'] and | |
each_record['type'] == params['type'] and | |
each_record['value'] == params['value']): | |
return True | |
return False | |
def run_module(): | |
# Define module parameters | |
module_args = dict( | |
api_key = dict(type='str', required=True), | |
comment = dict(type='str', required=False), | |
name = dict(type='str', required=True), | |
state = dict(type='str', required=False), | |
type = dict(type='str', required=True), | |
value = dict(type='str', required=True) | |
) | |
# This module's result dict, returned back to the play | |
result = dict( | |
changed=False, | |
response=dict() | |
) | |
# Instantiate the module | |
module = AnsibleModule( | |
argument_spec=module_args, | |
supports_check_mode=True | |
) | |
# API key | |
api_key = module.params['api_key'] | |
# Handle check mode TODO: make this actually check | |
if module.check_mode: | |
module.exit_json(**result) | |
# Prepare the desired state of the record | |
target_state = module.params['state'] or "present" | |
target_record = dict( | |
record = module.params['name'], | |
type = module.params['type'], | |
value = module.params['value'], | |
comment = module.params['comment'] | |
) | |
# Get the current records | |
records = list_records(api_key) | |
# Check for an existing matching record | |
record_exists = match_record(records, target_record) | |
# Expected API response | |
response = dict( | |
result = "", | |
data = "" | |
) | |
# Do the thing | |
if target_state == "present" and not record_exists: | |
response = add_record(api_key, target_record) | |
elif target_state == "absent" and record_exists: | |
response = remove_record(api_key, target_record) | |
# Check the results | |
result['response'] = response | |
if response['result'] == "success": | |
result['changed'] = True | |
elif response['result'] == "": | |
result['changed'] = False | |
else: | |
module.fail_json(msg=response['data'], **result) | |
# Return the results | |
module.exit_json(**result) | |
def main(): | |
run_module() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment