Files
deb-python-dcos/dcos/api/marathon.py
2015-01-26 13:49:14 -08:00

177 lines
5.0 KiB
Python

import json
import requests
from dcos.api import errors
class Client(object):
"""Class for talking to the Marathon server. """
def __init__(self, host, port):
"""Constructs interface for talking Marathon.
:param host: Host for the Marathon server.
:type host: str
:param port: Port for the Marathon server.
:type port: int
"""
self._url_pattern = "http://{host}:{port}/{path}"
self._host = host
self._port = port
def _create_url(self, path):
"""Creates the url from the provided path
:param path: Url path
:type path: str
:returns: Constructed url
:rtype: str
"""
return self._url_pattern.format(
host=self._host,
port=self._port,
path=path)
def _sanitize_app_id(self, app_id):
# Add a leading '/' if necessary.
if not app_id.startswith('/'):
app_id = '/' + app_id
return app_id
def _response_to_error(self, response):
return Error('Error: {}'.format(response.json()['message']))
def get_app(self, app_id):
"""Get a list of known applications.
:param app_id: The ID of the application to suspend.
:type app_id: str
:returns: List of known applications.
:rtype: (list of dictionaries, Error)
"""
app_id = self._sanitize_app_id(app_id)
url = self._create_url('v2/apps' + app_id)
response = requests.get(url)
if response.status_code == 200:
app = response.json()['app']
return (app, None)
else:
return (None, self._response_to_error(response))
def get_apps(self):
"""Get a list of known applications.
:returns: List of known applications.
:rtype: (list of dictionaries, Error)
"""
url = self._create_url('v2/apps')
response = requests.get(url)
if response.status_code == 200:
apps = response.json()['apps']
return (apps, None)
else:
return (None, self._response_to_error(response))
def start_app(self, app_resource):
"""Create and start a new application.
:param app_resource: Application resource
:type app_resource: dict, bytes, or file
:returns: Status of trying to start the application
:rtype: (bool, Error)
"""
url = self._create_url('v2/apps')
response = requests.post(url, data=app_resource)
if response.status_code == 201:
return (True, None)
else:
return (None, self._response_to_error(response))
def scale_app(self, app_id, instances, force=None):
"""Scales an application to zero instances.
:param app_id: The ID of the application to suspend.
:type app_id: str
:param instances: The requested number of instances.
:type instances: int
:param force: Whether to override running deployments.
:type force: bool
:returns: The resulting deployment ID.
:rtype: (bool, Error)
"""
if force is None:
force = False
app_id = self._sanitize_app_id(app_id)
forceQuery = ''
if force:
forceQuery = '?force=true'
url = self._create_url('v2/apps' + app_id + forceQuery)
scale_json = json.loads('{ "instances": %d }' % int(instances))
response = requests.put(url, json=scale_json)
if response.status_code == 200:
deployment = response.json()['deploymentId']
return (deployment, None)
else:
return (None, self._response_to_error(response))
def suspend_app(self, app_id, force=None):
"""Scales an application to zero instances.
:param app_id: The ID of the application to suspend.
:type app_id: str
:param force: Whether to override running deployments.
:type force: bool
:returns: The resulting deployment ID.
:rtype: (bool, Error)
"""
return self.scale_app(app_id, 0, force)
def remove_app(self, app_id):
"""Completely removes the requested application.
:param app_id: The ID of the application to suspend.
:type app_id: str
:returns: Status of trying to remove the application.
:rtype: (bool, Error)
"""
app_id = self._sanitize_app_id(app_id)
url = self._create_url('v2/apps' + app_id + '?force=true')
response = requests.delete(url)
if response.status_code == 200:
return (True, None)
else:
return (None, self._response_to_error(response))
class Error(errors.Error):
def __init__(self, message):
"""Constructs error for Marathon calls
:param message: Error message
:type message: str
"""
self._message = message
def error(self):
"""Return error message
:returns: The error message
:rtype: str
"""
return self._message