copy improvements from openappstack/cosmos.py to this repo

parent b9adfa6a
......@@ -14,6 +14,7 @@ import requests
from tabulate import tabulate
from pytz import timezone
# Helper functions
def request_api(resource: str, request_type: str = 'GET',
data: str = ''):
......@@ -51,11 +52,9 @@ def request_api(resource: str, request_type: str = 'GET',
if response.content:
log.debug('Response: %s\n', response.json())
return json.loads(response.content.decode('utf-8'))
else:
return None
else:
raise requests.HTTPError('WARNING: Got response code ',
response.status_code, response.text)
return None
raise requests.HTTPError('WARNING: Got response code ',
response.status_code, response.text)
# API calls
......@@ -92,7 +91,7 @@ def create_domain_record(domain: str, name: str, data: str,
return response['domain_record']
def create_droplet(name: str, ssh_key_id: int, region: str = 'ams1',
def create_droplet(name: str, ssh_key_id: int, region: str = 'ams1', # pylint: disable=too-many-arguments
size: int = 2048, disk: int = 20, image: int = 18):
"""Create a droplet.
......@@ -120,36 +119,37 @@ def create_droplet(name: str, ssh_key_id: int, region: str = 'ams1',
return response
def delete_domain_record(domain: str, id: int):
def delete_domain_record(domain: str, record_id: int):
"""Delete a domain record."""
log.info('Deleting domain record %s', id)
response = request_api('domains/{0}/records/{1}'.format(domain, id),
log.info('Deleting domain record %s', record_id)
response = request_api('domains/{0}/records/{1}'.format(domain, record_id),
'DELETE')
return response
def delete_domain_records_by_name(domain: str, name_regex: str):
"""Delete all domain records in a given domain matching a regex.
r"""Delete all domain records in a given domain matching a regex.
Examples:
delete_domain_records_by_name('openappstack.net', '^\*.ci-')
delete_domain_records_by_name('openappstack.net', '^ci-')
"""
all = get_domain_records_by_name(domain, name_regex)
for record in all:
all_records = get_domain_records_by_name(domain, name_regex)
for record in all_records:
delete_domain_record(domain, record['id'])
def delete_droplet(id: int):
def delete_droplet(droplet_id: int):
"""Delete a droplet. Droplet needs to be stopped first."""
log.info('Deleting %s', id)
response = request_api('droplets/{0}'.format(id), 'DELETE')
log.info('Deleting %s', droplet_id)
response = request_api('droplets/{0}'.format(droplet_id), 'DELETE')
return response
def get_domain_record(domain: str, id: int):
def get_domain_record(domain: str, droplet_id: int):
"""Get details for given domain record."""
response = request_api('domains/{0}/records/{1}'.format(domain, id))
response = request_api('domains/{0}/records/{1}'.format(domain, droplet_id))
return response['domain_record']
......@@ -206,14 +206,15 @@ def get_droplets_by_name(name_regex: str):
get_droplets_by_name(name_regex='^ci\d+')
"""
all_droplets = get_droplets()
log.debug(all_droplets)
matching = [droplet for droplet in all_droplets
if re.match('^ci+', droplet['name'])]
if re.match(name_regex, droplet['name'])]
return matching
def get_droplet(id: int):
def get_droplet(droplet_id: int):
"""Get information about specified droplet."""
response = request_api('droplets/{0}'.format(id))
response = request_api('droplets/{0}'.format(droplet_id))
return response['droplet']
......@@ -223,11 +224,13 @@ def list_domain_records(domain: str):
log.debug(json.dumps(records, sort_keys=True, indent=2))
table_records = [[
record['id'], record['name'], record['type'], record['data']]
for record in records]
table_records = [
[
record['id'], record['name'], record['type'], record['data']
] for record in records
]
log.info(tabulate(table_records,
headers=['ID', 'Name', 'Type', 'Data']))
headers=['ID', 'Name', 'Type', 'Data']))
def list_droplets():
......@@ -249,79 +252,87 @@ def list_droplets():
headers=['ID', 'Name', 'IPv4', 'Status']))
def shutdown_droplet(id: int):
def shutdown_droplet(droplet_id: int):
"""Shut down specified droplet (through a power_off call)."""
log.info('Shutting down %s', id)
log.info('Shutting down %s', droplet_id)
data = {"type": "power_off"}
response = request_api('droplets/{0}/actions'.format(id), 'POST', data)
response = request_api('droplets/{0}/actions'.format(droplet_id), 'POST', data)
return response
def status_droplet(id: int):
def status_droplet(droplet_id: int):
"""Get status of specified droplet."""
response = get_droplet(id)
response = get_droplet(droplet_id)
return response['status']
def terminate_droplet(id: int):
def terminate_droplet(droplet_id: int):
"""Terminate a droplet by powering it down and deleting it."""
shutdown_droplet(id)
wait_for_state(id, 'stopped')
delete_droplet(id)
shutdown_droplet(droplet_id)
wait_for_state(droplet_id, 'stopped')
delete_droplet(droplet_id)
def terminate_droplets_by_name(name_regex: str, ndays: int = 0, domain: str = 'openappstack.net'):
def terminate_droplets_by_name(name_regex: str, ndays: int = 0,
domain: str = 'openappstack.net'):
r"""
Terminate droplets matching a regex and for x days older than current day.
Droplets defined on the env variable NO_TERMINATE_DROPLETS will not be delated
Terminate droplets matching a regex and for x days older than current day.
Droplets defined on the env variable NO_TERMINATE_DROPLETS will not be
delated
Example how to terminate all CI instances:
terminate_old_droplets(name_regex='^ci\d+', ndays=5)
will match i.e 'ci1234' , 'ci1', with a creation time older than 5 days
"""
threshold_time = (datetime.now(tz=timezone('Europe/Stockholm')) - timedelta(days=ndays)).strftime("%Y-%m-%dT%H:%M:%S+00:00")
all = get_droplets()
threshold_time = (datetime.now(tz=timezone('Europe/Stockholm')) -
timedelta(days=ndays)).\
strftime("%Y-%m-%dT%H:%M:%S+00:00")
all_droplets = get_droplets()
noterminate_droplets = []
if 'NO_TERMINATE_DROPLETS' in os.environ:
noterminate_droplets = os.environ['NO_TERMINATE_DROPLETS'].split(',')
for droplet in all:
for droplet in all_droplets:
if droplet['name'] not in noterminate_droplets:
if re.match(name_regex, droplet['name']):
if droplet['created_at'] < threshold_time:
delete_domain_records_by_name(domain, '^\*.'+droplet['name'])
delete_domain_records_by_name(
domain, r'^\*.'+droplet['name'])
delete_domain_records_by_name(domain, '^'+droplet['name'])
terminate_droplet(droplet['id'])
def wait_for_ssh(ip: str):
def wait_for_ssh(droplet_ip: str):
"""Wait for ssh to be reachable on port 22."""
log.info('Waiting for ssh to become available on ip %s', ip)
log.info('Waiting for ssh to become available on ip %s', droplet_ip)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while sock.connect_ex((ip, 22)) != 0:
while sock.connect_ex((droplet_ip, 22)) != 0:
sleep(1)
log.info('SSH became available on ip %s', droplet_ip)
def wait_for_state(id: int, state):
def wait_for_state(droplet_id: int, state):
"""Wait for a droplet to reach a certain state."""
log.info('Waiting for droplet %s to reach %s state...', id, state)
status = status_droplet(id)
log.info('Waiting for droplet %s to reach %s state...', droplet_id, state)
status = status_droplet(droplet_id)
log.debug(status)
while status != state:
sleep(1)
status = status_droplet(id)
status = status_droplet(droplet_id)
# When called from from ipython, setup
# logging to console
try:
__IPYTHON__
log = logging.getLogger()
__IPYTHON__ # pylint: disable=pointless-statement
log = logging.getLogger() # pylint: disable=invalid-name
log.addHandler(logging.StreamHandler())
log.setLevel(logging.INFO)
except NameError:
log = logging.getLogger(__name__)
log = logging.getLogger(__name__) # pylint: disable=invalid-name
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment