#!/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(ctx) 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, [])