marathon: add dcos marathon task kill command (#971)
This commit is contained in:
committed by
tamarrow
parent
9f20ab9a78
commit
fcd4cec620
@@ -39,6 +39,7 @@ Usage:
|
|||||||
dcos marathon debug details <app-id> [--json]
|
dcos marathon debug details <app-id> [--json]
|
||||||
dcos marathon task list [--json <app-id>]
|
dcos marathon task list [--json <app-id>]
|
||||||
dcos marathon task stop [--wipe] <task-id>
|
dcos marathon task stop [--wipe] <task-id>
|
||||||
|
dcos marathon task kill [--scale] [--wipe] [--json] [<task-ids>...]
|
||||||
dcos marathon task show <task-id>
|
dcos marathon task show <task-id>
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
@@ -109,6 +110,8 @@ Commands:
|
|||||||
List all tasks.
|
List all tasks.
|
||||||
task stop
|
task stop
|
||||||
Stop a task.
|
Stop a task.
|
||||||
|
task kill
|
||||||
|
Kill one or more tasks.
|
||||||
task show
|
task show
|
||||||
List a specific task.
|
List a specific task.
|
||||||
|
|
||||||
@@ -178,5 +181,7 @@ Positional Arguments:
|
|||||||
If omitted, properties are read from a JSON object provided on stdin.
|
If omitted, properties are read from a JSON object provided on stdin.
|
||||||
<task-id>
|
<task-id>
|
||||||
The task ID.
|
The task ID.
|
||||||
|
<task_ids>
|
||||||
|
List of task IDs.
|
||||||
<scale-factor>
|
<scale-factor>
|
||||||
The factor to scale an application group by.
|
The factor to scale an application group by.
|
||||||
|
|||||||
@@ -80,6 +80,11 @@ def _cmds():
|
|||||||
arg_keys=['<task-id>', '--wipe'],
|
arg_keys=['<task-id>', '--wipe'],
|
||||||
function=subcommand.task_stop),
|
function=subcommand.task_stop),
|
||||||
|
|
||||||
|
cmds.Command(
|
||||||
|
hierarchy=['marathon', 'task', 'kill'],
|
||||||
|
arg_keys=['<task-ids>', '--scale', '--wipe', '--json'],
|
||||||
|
function=subcommand.task_kill),
|
||||||
|
|
||||||
cmds.Command(
|
cmds.Command(
|
||||||
hierarchy=['marathon', 'task', 'show'],
|
hierarchy=['marathon', 'task', 'show'],
|
||||||
arg_keys=['<task-id>'],
|
arg_keys=['<task-id>'],
|
||||||
@@ -860,6 +865,49 @@ class MarathonSubcommand(object):
|
|||||||
emitter.publish(task)
|
emitter.publish(task)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def task_kill(self, task_ids, scale, wipe, json_):
|
||||||
|
"""Kill one or multiple Marathon tasks
|
||||||
|
|
||||||
|
:param task_ids: the id of the task
|
||||||
|
:type task_ids: [str]
|
||||||
|
:param scale: Scale the app down after killing the specified tasks
|
||||||
|
:type scale: bool
|
||||||
|
:param wipe: whether remove reservations and persistent volumes.
|
||||||
|
:type wipe: bool
|
||||||
|
:param json_: output JSON if true
|
||||||
|
:type json_: bool
|
||||||
|
:returns: process return code
|
||||||
|
:rtype: int
|
||||||
|
"""
|
||||||
|
|
||||||
|
client = self._create_marathon_client()
|
||||||
|
payload = client.kill_and_scale_tasks(task_ids, scale, wipe)
|
||||||
|
|
||||||
|
def print_deployment(deployment, json_):
|
||||||
|
if json_:
|
||||||
|
emitter.publish(deployment)
|
||||||
|
else:
|
||||||
|
emitter.publish('Created deployment: {}'.format(
|
||||||
|
deployment['deploymentId']))
|
||||||
|
|
||||||
|
def print_killed_tasks(payload, json_):
|
||||||
|
if json_:
|
||||||
|
emitter.publish(payload)
|
||||||
|
else:
|
||||||
|
emitter.publish('Killed tasks: {}'.format(
|
||||||
|
[task['id'] for task in payload['tasks']]))
|
||||||
|
|
||||||
|
if scale:
|
||||||
|
print_deployment(payload, json_)
|
||||||
|
else:
|
||||||
|
print_killed_tasks(payload, json_)
|
||||||
|
|
||||||
|
if len(payload['tasks']) == 0:
|
||||||
|
raise DCOSException(
|
||||||
|
'Failed to kill tasks. task-ids seems to be unknown')
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
def task_show(self, task_id):
|
def task_show(self, task_id):
|
||||||
"""
|
"""
|
||||||
:param task_id: the task id
|
:param task_id: the task id
|
||||||
|
|||||||
@@ -639,6 +639,57 @@ def test_stop_task_wipe():
|
|||||||
_stop_task(task_id, '--wipe')
|
_stop_task(task_id, '--wipe')
|
||||||
|
|
||||||
|
|
||||||
|
def test_kill_one_task():
|
||||||
|
with _zero_instance_app():
|
||||||
|
start_app('zero-instance-app', 1)
|
||||||
|
watch_all_deployments()
|
||||||
|
task_list = _list_tasks(1, 'zero-instance-app')
|
||||||
|
task_id = [task_list[0]['id']]
|
||||||
|
|
||||||
|
_kill_task(task_id)
|
||||||
|
|
||||||
|
|
||||||
|
def test_kill_two_tasks():
|
||||||
|
with _zero_instance_app():
|
||||||
|
start_app('zero-instance-app', 2)
|
||||||
|
watch_all_deployments()
|
||||||
|
task_list = _list_tasks(2, 'zero-instance-app')
|
||||||
|
task_ids = [task['id'] for task in task_list]
|
||||||
|
|
||||||
|
_kill_task(task_ids)
|
||||||
|
|
||||||
|
|
||||||
|
def test_kill_and_scale_task():
|
||||||
|
with _zero_instance_app():
|
||||||
|
start_app('zero-instance-app', 2)
|
||||||
|
watch_all_deployments()
|
||||||
|
task_list = _list_tasks(2, 'zero-instance-app')
|
||||||
|
task_id = [task_list[0]['id']]
|
||||||
|
|
||||||
|
_kill_task(task_id, scale=True)
|
||||||
|
|
||||||
|
task_list = _list_tasks(1, 'zero-instance-app')
|
||||||
|
|
||||||
|
|
||||||
|
def test_kill_unknown_task():
|
||||||
|
with _zero_instance_app():
|
||||||
|
start_app('zero-instance-app')
|
||||||
|
watch_all_deployments()
|
||||||
|
task_id = ['unknown-task-id']
|
||||||
|
|
||||||
|
_kill_task(task_id, expect_success=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_kill_task_wipe():
|
||||||
|
with _zero_instance_app():
|
||||||
|
start_app('zero-instance-app', 1)
|
||||||
|
watch_all_deployments()
|
||||||
|
task_list = _list_tasks(1, 'zero-instance-app')
|
||||||
|
task_id = [task_list[0]['id']]
|
||||||
|
|
||||||
|
_kill_task(task_id, wipe=True)
|
||||||
|
|
||||||
|
|
||||||
def test_stop_unknown_task():
|
def test_stop_unknown_task():
|
||||||
with _zero_instance_app():
|
with _zero_instance_app():
|
||||||
start_app('zero-instance-app')
|
start_app('zero-instance-app')
|
||||||
@@ -761,6 +812,28 @@ def _stop_task(task_id, wipe=None, expect_success=True):
|
|||||||
assert returncode == 1
|
assert returncode == 1
|
||||||
|
|
||||||
|
|
||||||
|
def _kill_task(task_ids, scale=None, wipe=None, expect_success=True):
|
||||||
|
cmd = ['dcos', 'marathon', 'task', 'kill', '--json'] + task_ids
|
||||||
|
if scale:
|
||||||
|
cmd.append('--scale')
|
||||||
|
if wipe:
|
||||||
|
cmd.append('--wipe')
|
||||||
|
returncode, stdout, stderr = exec_command(cmd)
|
||||||
|
|
||||||
|
if expect_success:
|
||||||
|
assert returncode == 0
|
||||||
|
assert stderr == b''
|
||||||
|
result = json.loads(stdout.decode('utf-8'))
|
||||||
|
if scale:
|
||||||
|
assert 'deploymentId' in result
|
||||||
|
else:
|
||||||
|
assert sorted(
|
||||||
|
[task['id'] for task in result['tasks']]) == sorted(task_ids)
|
||||||
|
|
||||||
|
else:
|
||||||
|
assert returncode == 1
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def _zero_instance_app():
|
def _zero_instance_app():
|
||||||
with app('tests/data/marathon/apps/zero_instance_sleep.json',
|
with app('tests/data/marathon/apps/zero_instance_sleep.json',
|
||||||
|
|||||||
@@ -387,6 +387,37 @@ class Client(object):
|
|||||||
response = self._rpc.http_req(http.delete, path, params=params)
|
response = self._rpc.http_req(http.delete, path, params=params)
|
||||||
return response.json()
|
return response.json()
|
||||||
|
|
||||||
|
def kill_and_scale_tasks(self, task_ids, scale=None, wipe=None):
|
||||||
|
"""Kills the tasks for a given application,
|
||||||
|
and can target a given agent, with a future target scale
|
||||||
|
|
||||||
|
:param task_ids: a list of task ids to kill
|
||||||
|
:type task_ids: list
|
||||||
|
:param scale: Scale the app down after killing the specified tasks
|
||||||
|
:type scale: bool
|
||||||
|
:param wipe: whether remove reservations and persistent volumes.
|
||||||
|
:type wipe: bool
|
||||||
|
:returns: If scale=false, all tasks that were killed are returned.
|
||||||
|
If scale=true, than a deployment is triggered and the
|
||||||
|
deployment id and version returned.
|
||||||
|
:rtype: list | dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
path = 'v2/tasks/delete'
|
||||||
|
|
||||||
|
if scale:
|
||||||
|
params['scale'] = scale
|
||||||
|
if wipe:
|
||||||
|
params['wipe'] = wipe
|
||||||
|
|
||||||
|
response = self._rpc.http_req(http.post,
|
||||||
|
path,
|
||||||
|
params=params,
|
||||||
|
json={'ids': task_ids})
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
|
||||||
def restart_app(self, app_id, force=False):
|
def restart_app(self, app_id, force=False):
|
||||||
"""Performs a rolling restart of all of the tasks.
|
"""Performs a rolling restart of all of the tasks.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user