dcos service --completed

This commit is contained in:
Michael Gummelt
2015-08-28 11:43:06 -07:00
parent 99fe8a45f9
commit 657989a299
6 changed files with 95 additions and 82 deletions

View File

@@ -2,7 +2,7 @@
Usage:
dcos service --info
dcos service [--inactive --json]
dcos service [--completed --inactive --json]
dcos service log [--follow --lines=N --ssh-config-file=<path>]
<service> [<file>]
dcos service shutdown <service-id>
@@ -10,22 +10,28 @@ Usage:
Options:
-h, --help Show this screen
--info Show a short description of this subcommand
--ssh-config-file=<path> Path to SSH config file. Used to access
marathon logs.
--follow Print data as the file grows
--completed Show completed services in addition to active
ones. Completed services are those that have
been disconnected from master, and have reached
their failover timeout, or have been explicitly
shutdown via the /shutdown endpoint.
--inactive Show inactive services in addition to active
ones. Inactive services are those that have
been disconnected from master, but haven't yet
reached their failover timeout.
--info Show a short description of this subcommand
--follow Print data as the file grows
--json Print json-formatted services
--lines=N Print the last N lines [default: 10]
--ssh-config-file=<path> Path to SSH config file. Used to access
marathon logs.
--version Show version
Positional Arguments:
@@ -94,7 +100,7 @@ def _cmds():
cmds.Command(
hierarchy=['service'],
arg_keys=['--inactive', '--json'],
arg_keys=['--inactive', '--completed', '--json'],
function=_service),
]
@@ -110,9 +116,7 @@ def _info():
return 0
# TODO (mgummelt): support listing completed services as well.
# blocked on framework shutdown.
def _service(inactive, is_json):
def _service(inactive, completed, is_json):
"""List dcos services
:param inactive: If True, include completed tasks
@@ -124,7 +128,9 @@ def _service(inactive, is_json):
:rtype: int
"""
services = mesos.get_master().frameworks(inactive=inactive)
services = mesos.get_master().frameworks(
inactive=inactive,
completed=completed)
if is_json:
emitter.publish([service.dict() for service in services])

View File

@@ -2,7 +2,7 @@ Manage DCOS services
Usage:
dcos service --info
dcos service [--inactive --json]
dcos service [--completed --inactive --json]
dcos service log [--follow --lines=N --ssh-config-file=<path>]
<service> [<file>]
dcos service shutdown <service-id>
@@ -10,22 +10,28 @@ Usage:
Options:
-h, --help Show this screen
--info Show a short description of this subcommand
--ssh-config-file=<path> Path to SSH config file. Used to access
marathon logs.
--follow Print data as the file grows
--completed Show completed services in addition to active
ones. Completed services are those that have
been disconnected from master, and have reached
their failover timeout, or have been explicitly
shutdown via the /shutdown endpoint.
--inactive Show inactive services in addition to active
ones. Inactive services are those that have
been disconnected from master, but haven't yet
reached their failover timeout.
--info Show a short description of this subcommand
--follow Print data as the file grows
--json Print json-formatted services
--lines=N Print the last N lines [default: 10]
--ssh-config-file=<path> Path to SSH config file. Used to access
marathon logs.
--version Show version
Positional Arguments:

View File

@@ -11,6 +11,7 @@ def framework_fixture():
"active": True,
"checkpoint": True,
"completed_tasks": [],
"executors": [],
"failover_timeout": 604800,
"hostname": "mesos.vm",
"id": "20150502-231327-16842879-5050-3889-0000",

View File

@@ -377,15 +377,23 @@ def delete_zk_nodes():
:rtype: None
"""
base_url = os.environ['EXHIBITOR_URL']
base_path = 'exhibitor/v1/explorer/znode/{}'
for znode in ['universe', 'cassandra-mesos', 'chronos']:
znode_url = urllib.parse.urljoin(
base_url,
base_path.format(znode))
delete_zk_node(znode)
requests.delete(znode_url)
def delete_zk_node(znode):
"""Delete Zookeeper node
:param znode: znode to delete
:type znode: str
:rtype: None
"""
dcos_url = util.get_config_vals(['core.dcos_url'])[0]
znode_url = urllib.parse.urljoin(
dcos_url,
'/exhibitor/exhibitor/v1/explorer/znode/{}'.format(znode))
requests.delete(znode_url)
def assert_lines(cmd, num_lines):

View File

@@ -5,19 +5,11 @@ import time
import dcos.util as util
from dcos.util import create_schema
import pytest
from ..fixtures.service import framework_fixture
from .common import (assert_command, assert_lines, delete_zk_nodes,
exec_command, get_services, package_install,
package_uninstall, service_shutdown, ssh_output,
watch_all_deployments)
@pytest.fixture(scope="module")
def zk_znode(request):
request.addfinalizer(delete_zk_nodes)
return request
from .common import (assert_command, assert_lines, delete_zk_node,
delete_zk_nodes, exec_command, get_services,
package_install, package_uninstall, service_shutdown,
ssh_output, watch_all_deployments)
def setup_module(module):
@@ -30,44 +22,9 @@ def teardown_module(module):
def test_help():
stdout = b"""Manage DCOS services
Usage:
dcos service --info
dcos service [--inactive --json]
dcos service log [--follow --lines=N --ssh-config-file=<path>]
<service> [<file>]
dcos service shutdown <service-id>
Options:
-h, --help Show this screen
--info Show a short description of this subcommand
--ssh-config-file=<path> Path to SSH config file. Used to access
marathon logs.
--follow Print data as the file grows
--inactive Show inactive services in addition to active
ones. Inactive services are those that have
been disconnected from master, but haven't yet
reached their failover timeout.
--json Print json-formatted services
--lines=N Print the last N lines [default: 10]
--version Show version
Positional Arguments:
<file> Output this file. [default: stdout]
<service> The DCOS Service name.
<service-id> The DCOS Service ID
"""
assert_command(['dcos', 'service', '--help'], stdout=stdout)
with open('tests/data/help/service.txt') as content:
assert_command(['dcos', 'service', '--help'],
stdout=content.read().encode('utf-8'))
def test_info():
@@ -87,7 +44,7 @@ def test_service_table():
assert_lines(['dcos', 'service'], 3)
def test_service_inactive(zk_znode):
def test_service_inactive():
package_install('cassandra', True)
# wait long enough for it to register
@@ -108,7 +65,8 @@ def test_service_inactive(zk_znode):
# assert only marathon and chronos are active
get_services(2)
# assert marathon, chronos, and cassandra are listed with --inactive
# assert marathon, chronos, and cassandra are inactive
services = get_services(args=['--inactive'])
assert len(services) >= 3
@@ -120,6 +78,38 @@ def test_service_inactive(zk_znode):
# assert marathon, chronos are only listed with --inactive
get_services(2, ['--inactive'])
delete_zk_node('cassandra-mesos')
def test_service_completed():
package_install('cassandra', True)
time.sleep(5)
services = get_services(3)
# get cassandra's framework ID
cassandra_id = None
for service in services:
if service['name'] == 'cassandra.dcos':
cassandra_id = service['id']
break
assert cassandra_id is not None
assert_command(['dcos', 'marathon', 'group', 'remove', '/cassandra'])
service_shutdown(cassandra_id)
delete_zk_node('cassandra-mesos')
# assert cassandra is not running
services = get_services(2)
assert not any(service['id'] == cassandra_id for service in services)
# assert cassandra is completed
services = get_services(args=['--completed'])
assert len(services) >= 3
assert any(service['id'] == cassandra_id for service in services)
def test_log():
returncode, stdout, stderr = exec_command(
@@ -194,7 +184,7 @@ def test_log_lines():
assert_lines(['dcos', 'service', 'log', 'chronos', '--lines=4'], 4)
def test_log_multiple_apps(zk_znode):
def test_log_multiple_apps():
package_install('marathon', True)
package_install('marathon', True,
['--options=tests/data/service/marathon-user2.json',
@@ -219,6 +209,7 @@ def _get_schema(service):
schema = create_schema(service.dict())
schema['required'].remove('reregistered_time')
schema['required'].remove('pid')
schema['required'].remove('executors')
schema['properties']['offered_resources']['required'].remove('ports')
schema['properties']['resources']['required'].remove('ports')
schema['properties']['used_resources']['required'].remove('ports')

View File

@@ -491,10 +491,11 @@ class Master(object):
:returns: a list of frameworks
"""
keys = ['frameworks']
if completed:
keys.append('completed_frameworks')
for framework in _merge(self.state(), keys):
for framework in self.state()['completed_frameworks']:
yield framework
for framework in self.state()['frameworks']:
if inactive or framework['active']:
yield framework