Skip to content

Instantly share code, notes, and snippets.

@pebreo
Forked from dankrause/_hover_example.py
Created September 27, 2013 22:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pebreo/6736341 to your computer and use it in GitHub Desktop.
Save pebreo/6736341 to your computer and use it in GitHub Desktop.
import requests
class HoverException(Exception):
pass
class HoverAPI(object):
def __init__(self, username, password):
params = {"username": username, "password": password}
r = requests.post("https://www.hover.com/signin", params=params)
if not r.ok or "hoverauth" not in r.cookies:
raise HoverException(r)
self.cookies = {"hoverauth": r.cookies["hoverauth"]}
def call(self, method, resource, data=None):
url = "https://www.hover.com/api/{0}".format(resource)
r = requests.request(method, url, data=data, cookies=self.cookies)
if not r.ok:
raise HoverException(r)
if r.content:
body = r.json()
if "succeeded" not in body or body["succeeded"] is not True:
raise HoverException(body)
return body
# connect to the API using your account
client = HoverAPI("myusername", "mypassword")
# get details of a domains without DNS records
client.call("get", "domains")
# get all domains and DNS records
client.call("get", "dns")
# notice the "id" field of domains in response to the above calls - that's needed
# to address the domains individually, like so:
# get details of a specific domain without DNS records
client.call("get", "domains/dom123456")
# get DNS records of a specific domain:
client.call("get", "domains/dom123456/dns")
# create a new A record:
record = {"name": "mysubdomain", "type": "A", "content": "127.0.0.1"}
client.call("post", "domains/dom123456/dns", record)
# create a new SRV record
# note that content is "{priority} {weight} {port} {target}"
record = {"name": "mysubdomain", "type": "SRV", "content": "10 10 123 __service"}
client.call("post", "domains/dom123456/dns", record)
# create a new MX record
# note that content is "{priority} {host}"
record = {"name": "mysubdomain", "type": "MX", "content": "10 mail"}
client.call("post", "domains/dom123456/dns", record)
# notice the "id" field of DNS records in the above calls - that's
# needed to address the DNS records individually, like so:
# update an existing DNS record
client.call("put", "dns/dns1234567", {"content": "127.0.0.1"})
# delete a DNS record:
client.call("delete", "dns/dns1234567")
#!/usr/bin/python
import ConfigParser
import requests
import optparse
import sys
# This is a command-line script to import and export DNS records for a
# single domain into or out of a hover account. Run it like so:
# ./bulkhover.py -u USERNAME -p PASSWORD (import|export) DOMAIN DNS_FILE
# or create a config file like this:
#
# [hover]
# username=USERNAME
# password=PASSWORD
#
# and run it like this:
# ./bulkhover.py -c PATH_TO_CONF (import|export) DOMAIN DNS_FILE
#
# The DNS file should have one record per line, in the format:
# {name} {type} {content}
#
# For example:
#
# www A 127.0.0.1
# @ MX 10 example.com
#
# You can even copy the entire contents of one domain to another, like so:
# ./bulkhover.py -c CONF export example.com - | ./bulkhover.py -c CONF -f import other.com -
class HoverException(Exception):
pass
class HoverAPI(object):
def __init__(self, username, password):
params = {"username": username, "password": password}
r = requests.post("https://www.hover.com/signin", params=params)
if not r.ok or "hoverauth" not in r.cookies:
raise HoverException(r)
self.cookies = {"hoverauth": r.cookies["hoverauth"]}
def call(self, method, resource, data=None):
url = "https://www.hover.com/api/{0}".format(resource)
r = requests.request(method, url, data=data, cookies=self.cookies)
if not r.ok:
raise HoverException(r)
if r.content:
body = r.json()
if "succeeded" not in body or body["succeeded"] is not True:
raise HoverException(body)
return body
def import_dns(username, password, domain, filename, flush=False):
try:
client = HoverAPI(username, password)
except HoverException as e:
raise HoverException("Authentication failed")
if flush:
records = client.call("get", "domains/{0}/dns".format(domain))["domains"][0]["entries"]
for record in records:
client.call("delete", "dns/{0}".format(record["id"]))
print "Deleted {name} {type} {content}".format(**record)
domain_id = client.call("get", "domains/{0}".format(domain))["domain"]["id"]
if filename == "-": filename = "/dev/stdin"
with open(filename, "r") as f:
for line in f:
parts = line.strip().split(" ", 2)
record = {"name": parts[0], "type": parts[1], "content": parts[2]}
client.call("post", "domains/{0}/dns".format(domain), record)
print "Created {name} {type} {content}".format(**record)
def export_dns(username, password, domain, filename):
try:
client = HoverAPI(username, password)
except HoverException as e:
raise HoverException("Authentication failed")
records = client.call("get", "domains/{0}/dns".format(domain))["domains"][0]["entries"]
if filename == "-": filename = "/dev/stdout"
with open(filename, "w") as f:
for record in records:
f.write("{name} {type} {content}\n".format(**record))
def main():
usage = "usage: %prog (-c CONF|-u USERNAME -p PASSWORD) (import|export) DOMAIN DNS_FILE"
description = "Import or export DNS records for a single domain in a hover account."
parser = optparse.OptionParser(usage=usage, description=description)
parser.add_option("-c", "--conf", default=None, help="The conf file that contains your username and password")
parser.add_option("-u", "--username", default=None, help="Your hover.com username")
parser.add_option("-p", "--password", default=None, help="Your hover.com password")
parser.add_option("-f", "--flush", default=False, action="store_true", help="Flush all DNS records associated with the domain before importing")
(options, args) = parser.parse_args()
if len(args) < 3:
parser.error("You must specify an operation, a domain, and a file")
operation, domain, filename = args
if operation not in ("import", "export"):
parser.error("Invalid operation: {0} - Valid operations are import and export".format(operation))
def get_conf(filename):
config = ConfigParser.ConfigParser()
config.read(filename)
items = dict(config.items("hover"))
return items["username"], items["password"]
if options.conf is None:
if not all((options.username, options.password)):
parser.error("You must specifiy either a conf file, or a username and password")
else:
username, password = options.username, options.password
else:
username, password = get_conf(options.conf)
if operation == "import":
import_dns(username, password, domain, filename, options.flush)
elif operation == "export":
export_dns(username, password, domain, filename)
if __name__ == "__main__":
try:
main()
except HoverException as e:
print "Failed while importing DNS: {0}".format(e)
sys.exit(1)
sys.exit(0)
#!/usr/bin/env python
"""
dynhover.py 1.1
Usage:
dynhover.py (-c <conf> | -u <user> -p <password>) <domain>
dynhover.py (-h | --help)
dynhover.py --version
Options:
-h --help Show this screen.
--version Show version.
-c --conf=<conf> Path to conf.
-u --username=<user> Your hover username.
-p --password=<pass> Your hover password.
"""
import ConfigParser
import docopt
import requests
import sys
class HoverException(Exception):
pass
class HoverAPI(object):
def __init__(self, username, password):
params = {"username": username, "password": password}
r = requests.post("https://www.hover.com/signin", params=params)
if not r.ok or "hoverauth" not in r.cookies:
raise HoverException(r)
self.cookies = {"hoverauth": r.cookies["hoverauth"]}
def call(self, method, resource, data=None):
url = "https://www.hover.com/api/{0}".format(resource)
r = requests.request(method, url, data=data, cookies=self.cookies)
if not r.ok:
raise HoverException(r)
if r.content:
body = r.json()
if "succeeded" not in body or body["succeeded"] is not True:
raise HoverException(body)
return body
def get_public_ip():
return requests.get("http://api.exip.org/?call=ip").content
def update_dns(username, password, fqdn):
try:
client = HoverAPI(username, password)
except HoverException as e:
raise HoverException("Authentication failed")
dns = client.call("get", "dns")
dns_id = None
for domain in dns["domains"]:
if fqdn == domain["domain_name"]:
fqdn = "@.{domain_name}".format(**domain)
for entry in domain["entries"]:
if entry["type"] != "A": continue
if "{0}.{1}".format(entry["name"], domain["domain_name"]) == fqdn:
dns_id = entry["id"]
break
if dns_id is None:
raise HoverException("No DNS record found for {0}".format(fqdn))
my_ip = get_public_ip()
response = client.call("put", "dns/{0}".format(dns_id), {"content": my_ip})
if "succeeded" not in response or response["succeeded"] is not True:
raise HoverException(response)
def main(args):
if args["--username"]:
username, password = args["--username"], args["--password"]
else:
config = ConfigParser.ConfigParser()
config.read(args["--conf"])
items = dict(config.items("hover"))
username, password = items["username"], items["password"]
domain = args["<domain>"]
try:
update_dns(username, password, domain)
except HoverException as e:
print "Unable to update DNS: {0}".format(e)
return 1
return 0
if __name__ == "__main__":
version = __doc__.strip().split("\n")[0]
args = docopt.docopt(__doc__, version=version)
status = main(args)
sys.exit(status)
#!/bin/bash
[[ $# -lt 3 ]] && echo "Usage: $0 USERNAME PASSWORD DNS_ID"
USERNAME=${1}
PASSWORD=${2}
DNS_ID=${3}
# find your DNS ID here: https://www.hover.com/api/domains/yourdomain.com/dns/
# (replace "yourdomain.com" with your actual domain, and look for the record
# you want to change. The ID looks like: dns1234567)
IP=$(curl "http://api.exip.org/?call=ip" -s)
curl "https://www.hover.com/api/dns/${DNS_ID}" \
-X PUT \
-d "content=${IP}" \
-s \
-b <(curl "https://www.hover.com/signin" \
-X POST \
-G \
-d "username=${USERNAME}" \
-d "password=${PASSWORD}" \
-s \
-o /dev/null \
-c -)
echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment