From 71833e1b880a739d6da3239b951b632f1da74219 Mon Sep 17 00:00:00 2001 From: Francesco Magliocca Date: Tue, 29 Mar 2022 22:48:42 +0200 Subject: [PATCH] Implement list dns records --- dominioctl.py | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100755 dominioctl.py diff --git a/dominioctl.py b/dominioctl.py new file mode 100755 index 0000000..67cb296 --- /dev/null +++ b/dominioctl.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 + +import http.client +import xml.etree.ElementTree as ElementTree +import sys +import os + +def read_api_key(): + return os.getenv('NAMESILO_API_KEY') + +def make_request_url(api_key, operation, args_dict): + """Helper function to create URLs for a given `operation`. + The arguments for the operation are passed in `args_dict` dictionary""" + + # Only version and response type currently supported by namesilo + API_VERSION = 1 + RESPONSE_TYPE = 'xml' + + url_template = "/api/{}?version={}&type={}&key={}" + url = url_template.format(operation, API_VERSION, RESPONSE_TYPE, api_key) + for name, value in args_dict.items(): + arg = "&{}={}".format(name, value) + url += arg + return url + +def http_get_request(hostname, req_url): + conn = http.client.HTTPSConnection(hostname) + conn.request('GET', req_url) + with conn.getresponse() as resp: + res = resp.read() + conn.close() + return res + +def make_request(api_key, operation, args_dict): + """Helper function to perform to perform the asked `operation`. + `args_dict` is a dict containing all the required arguments for the operation. + Returns the parsed xml body""" + NAMESILO_HOSTNAME = 'www.namesilo.com' + req_url = make_request_url(api_key, operation, args_dict) + # TODO: Maybe an incremental streaming solution is better + resp = http_get_request(NAMESILO_HOSTNAME, req_url) + return ElementTree.fromstring(resp) + +class Command: + """Base Command type""" + def run(self, ctx, args): + """Run command""" + pass + + def description(self): + """Command description""" + pass + + def print_help(self, ctx): + """Print help message for this command""" + pass + +class ListDnsRecords(Command): + def run(self, ctx, args): + if len(args) < 1: + print("Missing domain name argument") + self.print_help() + return + + domain = args[0] + self.list_dns_records_summary(ctx['api_key'], domain) + + def description(self): + return "Get a summary of the currently active DNS records for a domain" + + def print_help(self, ctx): + print(self.description()) + print("Usage: {} list-dns-records ".format(ctx['executable_name'])) + print("\ndomain-name\t domain name whose DNS records you want to see") + + def list_dns_records_summary(self, api_key, domain): + """Get a summary of the currently active DNS records for the given `domain`""" + xml_tree = make_request(api_key, "dnsListRecords", { "domain": domain }) + + code = xml_tree.find('./reply/code').text + if code != "300": + detail = xml_tree.find('./reply/detail').text + print("Error code {}: {}".format(code, detail)) + else: + print('record\thostname') + print('----------------') + for record in xml_tree.iter('resource_record'): + record_type = record.find('type').text + host = record.find('host').text + print("{}\t{}".format(record_type, host)) + +class Help(Command): + def run(self, ctx, args): + if len(args) > 0: + command_name = args[0] + if command_name in ctx['commands']: + ctx['commands'][command_name].print_help() + else: + print("Unknown command.") + else: + print("Available commands (run {} help for more info):".format(ctx['executable_name'])) + for name, cmd in ctx['commands'].items(): + print(name) + + def description(self): + return "Get help about commands (help )" + + def print_help(self, ctx): + print(self.description()) + print("Usage: {} help ".format(ctx['executable_name'])) + +# Main Program + +if __name__ == "__main__": + context = { + 'api_key': read_api_key(), + 'executable_name': sys.argv[0], + 'commands': { + 'list-dns-records': ListDnsRecords(), + 'help': Help() + } + } + + # Main program + + if len(sys.argv) > 1: + command_name = sys.argv[1] + if command_name in context['commands']: + # Take only the remainder of the arguments, + # they are arguments for the specified command + command_args = sys.argv[2:] + context['commands'][command_name].run(context, command_args) + + else: + print("Unknown command {}".format(command_name)) + Help().run(context, []) + else: + print("No command specified") + Help().run(context, [])