diff --git a/dcos/api/marathon.py b/dcos/api/marathon.py index 51fb086..e163170 100644 --- a/dcos/api/marathon.py +++ b/dcos/api/marathon.py @@ -327,6 +327,35 @@ class Client(object): else: return (None, self._response_to_error(response)) + def get_deployments(self, app_id=None): + """Returns a list of deployments, optionally limited to an app. + + :param app_id: the id of the application to restart + :type app_id: str + :returns: a list of deployments + :rtype: list of dict + """ + + url = self._create_url('v2/deployments') + + logger.info('Getting %r', url) + response = requests.get(url) + logger.info('Got (%r): %r', response.status_code, response.json()) + + if _success(response.status_code): + if app_id is not None: + app_id = normalize_app_id(app_id) + deployments = [ + deployment for deployment in response.json() + if app_id in deployment['affectedApps'] + ] + else: + deployments = response.json() + + return (deployments, None) + else: + return (None, self._response_to_error(response)) + class Error(errors.Error): """ Class for describing errors while talking to the Marathon server. diff --git a/dcos/cli/app/main.py b/dcos/cli/app/main.py index 174094d..ccd44c2 100644 --- a/dcos/cli/app/main.py +++ b/dcos/cli/app/main.py @@ -1,6 +1,7 @@ """ Usage: dcos app add + dcos app deployment list [] dcos app info dcos app list dcos app remove [--force] @@ -25,7 +26,7 @@ Options: negative integer and they represent the version from the currently deployed application definition. - --max-count= Maximun number of entries to try to fetch and + --max-count= Maximum number of entries to try to fetch and return Positional arguments: @@ -87,6 +88,11 @@ def _cmds(): arg_keys=['', '--max-count'], function=_version_list), + cmds.Command( + hierarchy=['deployment', 'list'], + arg_keys=[''], + function=_deployment_list), + cmds.Command(hierarchy=['list'], arg_keys=[], function=_list), cmds.Command( @@ -508,6 +514,28 @@ def _version_list(app_id, max_count): return 0 +def _deployment_list(app_id): + """ + :param app_id: the application id + :type app_id: str + :returns: process status + :rtype: int + """ + + client = marathon.create_client( + config.load_from_path( + os.environ[constants.DCOS_CONFIG_ENV])) + + deployments, err = client.get_deployments(app_id) + if err is not None: + emitter.publish(err) + return 1 + + emitter.publish(deployments) + + return 0 + + def _update_from_stdin(app_id, force): """ :param app_id: the id of the application diff --git a/integrations/cli/test_app.py b/integrations/cli/test_app.py index 16add58..83db135 100644 --- a/integrations/cli/test_app.py +++ b/integrations/cli/test_app.py @@ -10,6 +10,7 @@ def test_help(): assert returncode == 0 assert stdout == b"""Usage: dcos app add + dcos app deployment list [] dcos app info dcos app list dcos app remove [--force] @@ -34,7 +35,7 @@ Options: negative integer and they represent the version from the currently deployed application definition. - --max-count= Maximun number of entries to try to fetch and + --max-count= Maximum number of entries to try to fetch and return Positional arguments: @@ -414,6 +415,63 @@ def test_list_version_max_count(): _remove_app('zero-instance-app') +def test_list_empty_deployment(): + returncode, stdout, stderr = exec_command( + ['dcos', 'app', 'deployment', 'list']) + + assert returncode == 0 + assert stdout == b'[]\n' + assert stderr == b'' + + +def test_list_deployment(): + _add_app('tests/data/marathon/zero_instance_sleep.json') + _start_app('zero-instance-app') + + returncode, stdout, stderr = exec_command( + ['dcos', 'app', 'deployment', 'list']) + + result = json.loads(stdout.decode('utf-8')) + + assert returncode == 0 + assert len(result) == 1 + assert stderr == b'' + + _remove_app('zero-instance-app') + + +def test_list_deployment_missing_app(): + _add_app('tests/data/marathon/zero_instance_sleep.json') + _start_app('zero-instance-app') + + returncode, stdout, stderr = exec_command( + ['dcos', 'app', 'deployment', 'list', 'missing-id']) + + result = json.loads(stdout.decode('utf-8')) + + assert returncode == 0 + assert len(result) == 0 + assert stderr == b'' + + _remove_app('zero-instance-app') + + +def test_list_deployment_app(): + _add_app('tests/data/marathon/zero_instance_sleep.json') + _start_app('zero-instance-app') + + returncode, stdout, stderr = exec_command( + ['dcos', 'app', 'deployment', 'list', 'zero-instance-app']) + + result = json.loads(stdout.decode('utf-8')) + + assert returncode == 0 + assert len(result) == 1 + assert stderr == b'' + + _remove_app('zero-instance-app') + + def _list_apps(app_id=None): returncode, stdout, stderr = exec_command(['dcos', 'app', 'list'])