dominioctl/dominioctl.py

140 lines
4.5 KiB
Python
Executable File

#!/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 <domain-name>".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(ctx)
else:
print("Unknown command.")
else:
print("Available commands (run {} help <command-name> 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 <command-name>)"
def print_help(self, ctx):
print(self.description())
print("Usage: {} help <command-name>".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, [])