Merge pull request #42 from mesosphere/dcos-319-restart
dcos-319 Implements restarting tasks for app
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user