Merge pull request #42 from mesosphere/dcos-319-restart

dcos-319 Implements restarting tasks for app
This commit is contained in:
Connor Doyle
2015-02-22 20:07:38 -08:00
3 changed files with 130 additions and 15 deletions

View File

@@ -148,7 +148,10 @@ class Client(object):
"""
url = self._create_url('v2/apps')
logger.info('Getting %r', url)
response = requests.get(url)
logger.info('Got (%r): %r', response.status_code, response.json())
if _success(response.status_code):
apps = response.json()['apps']
@@ -197,10 +200,10 @@ class Client(object):
app_id = normalize_app_id(app_id)
if force is None or not force:
if not force:
params = None
else:
params = {'force': True}
params = {'force': 'true'}
url = self._create_url('v2/apps{}'.format(app_id), params)
@@ -226,17 +229,18 @@ class Client(object):
:rtype: (bool, Error)
"""
if force is None:
force = False
app_id = normalize_app_id(app_id)
params = None
if force:
params = {'force': True}
if not force:
params = None
else:
params = {'force': 'true'}
url = self._create_url('v2/apps{}'.format(app_id), params)
logger.info('Putting to %r', url)
response = requests.put(url, json={'instances': int(instances)})
logger.info('Got (%r): %r', response.status_code, response.json())
if _success(response.status_code):
deployment = response.json()['deploymentId']
@@ -268,26 +272,56 @@ class Client(object):
:rtype: Error
"""
if force is None:
force = False
app_id = normalize_app_id(app_id)
params = None
if force:
params = {'force': True}
if not force:
params = None
else:
params = {'force': 'true'}
url = self._create_url('v2/apps{}'.format(app_id), params)
logger.info('Deleting %r', url)
response = requests.delete(url)
logger.info('Got (%r)', response.status_code)
if _success(response.status_code):
return None
else:
return self._response_to_error(response)
def restart_app(self, app_id, force=None):
"""Performs a rolling restart of all of the tasks.
:param app_id: the id of the application to restart
:type app_id: str
:param force: whether to override running deployments
:type force: bool
:returns: the deployment id and version; Error otherwise
:rtype: (dict, Error)
"""
app_id = normalize_app_id(app_id)
if not force:
params = None
else:
params = {'force': 'true'}
url = self._create_url('v2/apps{}/restart'.format(app_id), params)
logger.info('Posting %r', url)
response = requests.post(url)
logger.info('Got (%r): %r', response.status_code, response.json())
if _success(response.status_code):
return (response.json(), None)
else:
return (None, self._response_to_error(response))
class Error(errors.Error):
""" Class for describing erros while talking to the Marathon server.
""" Class for describing errors while talking to the Marathon server.
:param message: Error message
:type message: str

View File

@@ -4,6 +4,7 @@ Usage:
dcos app info
dcos app list
dcos app remove [--force] <app-id>
dcos app restart [--force] <app-id>
dcos app show [--app-version=<app-version>] <app-id>
dcos app start [--force] <app-id> [<instances>]
dcos app stop [--force] <app-id>
@@ -81,6 +82,9 @@ def main():
if args['update']:
return _update(args['<app-id>'], args['<properties>'], args['--force'])
if args['restart']:
return _restart(args['<app-id>'], args['--force'])
emitter.publish(options.make_generic_usage_error(__doc__))
return 1
@@ -406,6 +410,43 @@ def _update(app_id, json_items, force):
return 0
def _restart(app_id, force):
"""
:param app_id: the id of the application
:type app_id: str
:param force: whether to override running deployments
:type force: bool
:returns: process status
:rtype: int
"""
client = marathon.create_client(
config.load_from_path(
os.environ[constants.DCOS_CONFIG_ENV]))
desc, err = client.get_app(app_id)
if err is not None:
emitter.publish(err)
return 1
if desc['instances'] <= 0:
app_id = marathon.normalize_app_id(app_id)
emitter.publish(
'Unable to restart application {!r} because it is stopped'.format(
app_id,
desc['instances']))
return 1
payload, err = client.restart_app(app_id, force)
if err is not None:
emitter.publish(err)
return 1
emitter.publish('Created deployment {}'.format(payload['deploymentId']))
return 0
def _update_from_stdin(app_id, force):
"""
:param app_id: the id of the application

View File

@@ -13,6 +13,7 @@ def test_help():
dcos app info
dcos app list
dcos app remove [--force] <app-id>
dcos app restart [--force] <app-id>
dcos app show [--app-version=<app-version>] <app-id>
dcos app start [--force] <app-id> [<instances>]
dcos app stop [--force] <app-id>
@@ -327,6 +328,45 @@ def test_update_app_from_stdin():
_remove_app('zero-instance-app')
def test_restarting_stopped_app():
_add_app('tests/data/marathon/zero_instance_sleep.json')
returncode, stdout, stderr = exec_command(
['dcos', 'app', 'restart', 'zero-instance-app'])
assert returncode == 1
assert stdout == (
b"Unable to restart application '/zero-instance-app' "
b"because it is stopped\n")
assert stderr == b''
_remove_app('zero-instance-app')
def test_restarting_missing_app():
returncode, stdout, stderr = exec_command(
['dcos', 'app', 'restart', 'missing-id'])
assert returncode == 1
assert stdout == b"Error: App '/missing-id' does not exist\n"
assert stderr == b''
@pytest.mark.skipif(True, reason='We need to wait for the start to finish')
def test_restarting_app():
_add_app('tests/data/marathon/zero_instance_sleep.json')
_start_app('zero-instance-app')
returncode, stdout, stderr = exec_command(
['dcos', 'app', 'restart', 'zero-instance-app'])
assert returncode == 1
assert stdout.decode().startswith('Created deployment ')
assert stderr == b''
_remove_app('zero-instance-app')
def _list_apps(app_id=None):
returncode, stdout, stderr = exec_command(['dcos', 'app', 'list'])