From 8c7d16196b4932221b42c19465eb22d3d07d815c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Armando=20Garc=C3=ADa=20Sancio?= Date: Sat, 21 Feb 2015 23:46:14 +0000 Subject: [PATCH] dcos-317 list versions for an app --- dcos/api/emitting.py | 3 +- dcos/api/marathon.py | 8 +++++ dcos/cli/app/main.py | 43 +++++++++++++++++++++-- integrations/cli/test_app.py | 66 +++++++++++++++++++++++++++++++++++- 4 files changed, 115 insertions(+), 5 deletions(-) diff --git a/dcos/api/emitting.py b/dcos/api/emitting.py index 327293b..8577390 100644 --- a/dcos/api/emitting.py +++ b/dcos/api/emitting.py @@ -63,7 +63,8 @@ def print_handler(event): if isinstance(event, basestring): print(event) elif isinstance(event, collections.Mapping) or isinstance(event, list): - print(json.dumps(event, sys.stdout, sort_keys=True, indent=2)) + json.dump(event, sys.stdout, sort_keys=True, indent=2) + print('') elif isinstance(event, errors.Error): print(event.error()) else: diff --git a/dcos/api/marathon.py b/dcos/api/marathon.py index 4e5fee1..51fb086 100644 --- a/dcos/api/marathon.py +++ b/dcos/api/marathon.py @@ -124,6 +124,14 @@ class Client(object): :rtype: (list of str, Error) """ + if max_count is not None and max_count <= 0: + return ( + None, + Error( + 'Maximum count must be a positive number: {}'.format( + max_count)) + ) + app_id = normalize_app_id(app_id) url = self._create_url('v2/apps{}/versions'.format(app_id)) diff --git a/dcos/cli/app/main.py b/dcos/cli/app/main.py index 2a3df32..1952e9d 100644 --- a/dcos/cli/app/main.py +++ b/dcos/cli/app/main.py @@ -9,6 +9,7 @@ Usage: dcos app start [--force] [] dcos app stop [--force] dcos app update [--force] [...] + dcos app version list [--max-count=] Options: -h, --help Show this screen @@ -24,12 +25,15 @@ 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 + return Positional arguments: The application id + The number of instances to start Optional key-value pairs to be included in the command. The separator between the key and value - must be the '=' character. E.g. cpus=2.0. + must be the '=' character. E.g. cpus=2.0 """ import json import os @@ -64,6 +68,9 @@ def main(): if args['add']: return _add() + if args['version'] and args['list']: + return _version_list(args[''], args['--max-count']) + if args['list']: return _list() @@ -232,8 +239,8 @@ def _start(app_id, instances, force): :param app_id: the id for the application :type app_id: str - :param json_items: the list of json item - :type json_items: list of str + :param instances: the number of instances to start + :type instances: str :param force: whether to override running deployments :type force: bool :returns: Process status @@ -447,6 +454,36 @@ def _restart(app_id, force): return 0 +def _version_list(app_id, max_count): + """ + :param app_id: the id of the application + :type app_id: str + :param max_count: the maximum number of version to fetch and return + :type max_count: str + :returns: process status + :rtype: int + """ + + if max_count is not None: + max_count, err = _parse_int(max_count) + if err is not None: + emitter.publish(err) + return 1 + + client = marathon.create_client( + config.load_from_path( + os.environ[constants.DCOS_CONFIG_ENV])) + + versions, err = client.get_app_versions(app_id, max_count) + if err is not None: + emitter.publish(err) + return 1 + + emitter.publish(versions) + + 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 cf3d26b..16add58 100644 --- a/integrations/cli/test_app.py +++ b/integrations/cli/test_app.py @@ -18,6 +18,7 @@ def test_help(): dcos app start [--force] [] dcos app stop [--force] dcos app update [--force] [...] + dcos app version list [--max-count=] Options: -h, --help Show this screen @@ -33,12 +34,15 @@ 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 + return Positional arguments: The application id + The number of instances to start Optional key-value pairs to be included in the command. The separator between the key and value - must be the '=' character. E.g. cpus=2.0. + must be the '=' character. E.g. cpus=2.0 """ assert stderr == b'' @@ -367,6 +371,49 @@ def test_restarting_app(): _remove_app('zero-instance-app') +def test_list_version_missing_app(): + returncode, stdout, stderr = exec_command( + ['dcos', 'app', 'version', 'list', 'missing-id']) + + assert returncode == 1 + assert stdout == b"Error: App '/missing-id' does not exist\n" + assert stderr == b'' + + +def test_list_version_negative_max_count(): + returncode, stdout, stderr = exec_command( + ['dcos', 'app', 'version', 'list', 'missing-id', '--max-count=-1']) + + assert returncode == 1 + assert stdout == b'Maximum count must be a positive number: -1\n' + assert stderr == b'' + + +def test_list_version_app(): + _add_app('tests/data/marathon/zero_instance_sleep.json') + _list_versions('zero-instance-app', 1) + + _update_app( + 'zero-instance-app', + 'tests/data/marathon/update_zero_instance_sleep.json') + _list_versions('zero-instance-app', 2) + + _remove_app('zero-instance-app') + + +def test_list_version_max_count(): + _add_app('tests/data/marathon/zero_instance_sleep.json') + _update_app( + 'zero-instance-app', + 'tests/data/marathon/update_zero_instance_sleep.json') + + _list_versions('zero-instance-app', 1, 1) + _list_versions('zero-instance-app', 2, 2) + _list_versions('zero-instance-app', 2, 3) + + _remove_app('zero-instance-app') + + def _list_apps(app_id=None): returncode, stdout, stderr = exec_command(['dcos', 'app', 'list']) @@ -439,3 +486,20 @@ def _update_app(app_id, file_path): assert returncode == 0 assert stdout == b'' assert stderr == b'' + + +def _list_versions(app_id, expected_count, max_count=None): + cmd = ['dcos', 'app', 'version', 'list', app_id] + if max_count is not None: + cmd.append('--max-count={}'.format(max_count)) + + returncode, stdout, stderr = exec_command(cmd) + + result = json.loads(stdout.decode('utf-8')) + + assert returncode == 0 + assert isinstance(result, list) + assert len(result) == expected_count + assert stderr == b'' + + return result