From 13b5cb9ed127e2dd681de18d82f9281ebf0494b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gre=CC=81goire=20Morpain?= Date: Fri, 21 Apr 2017 14:17:06 +0200 Subject: [PATCH 1/2] aliases and autocomplete script --- MANIFEST.in | 1 + setup.py | 6 ++++++ shipami/cli.py | 18 +++++++++++++++++- shipami/shipami-complete.sh | 8 ++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 shipami/shipami-complete.sh diff --git a/MANIFEST.in b/MANIFEST.in index b5baa5c..78b2d67 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,6 +4,7 @@ exclude .travis.yml include README.rst include LICENSE include setup.cfg +include shipami-complete.sh prune .cache prune .git prune build diff --git a/setup.py b/setup.py index ddb823f..14ae191 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,12 @@ keywords='aws ec2 ami marketplace', packages=find_packages(exclude=['contrib', 'docs', 'tests*']), + package_data={ + 'codebuilder': [ + 'shipami-complete.sh' + ] + }, + include_package_data=True, install_requires=[ 'click==6.7', diff --git a/shipami/cli.py b/shipami/cli.py index 2debf0e..b91139d 100644 --- a/shipami/cli.py +++ b/shipami/cli.py @@ -28,7 +28,23 @@ def validate_filter(ctx, param, filters): raise click.BadParameter('filter must be in format "key=value"') return tuple(validated_filters) -@click.group() +class AliasedGroup(click.Group): + ALIASES = { + 'ls': 'list', + 'cp': 'copy', + 'rm': 'delete' + } + + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + + if self.ALIASES.get(cmd_name, None): + return click.Group.get_command(self, ctx, self.ALIASES[cmd_name]) + return None + +@click.group(cls=AliasedGroup) @click.version_option(VERSION) @click.option('--region') @click.option('-v', '--verbose', is_flag=True, default=False) diff --git a/shipami/shipami-complete.sh b/shipami/shipami-complete.sh new file mode 100644 index 0000000..3600ffb --- /dev/null +++ b/shipami/shipami-complete.sh @@ -0,0 +1,8 @@ +_shipami_completion() { + COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + _SHIPAMI_COMPLETE=complete $1 ) ) + return 0 +} + +complete -F _shipami_completion -o default shipami; From 37a66b40b8bd3ad3c0fe4bb8a2e6fdcf7b38c7c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gre=CC=81goire=20Morpain?= Date: Fri, 21 Apr 2017 14:29:30 +0200 Subject: [PATCH 2/2] add tests --- tests/test_cli.py | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index dd87f09..571ed2b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -89,6 +89,20 @@ def test_list(self, base_image, released_image): assert 'origin' not in lines[1] assert 'eu-west-1:{}'.format(base_image.id) in lines[1] + def test_list_aliased(self, base_image, released_image): + r = runner.invoke(shipami, ['ls']) + + lines = r.output.splitlines() + + assert r.exit_code == 0 + assert base_image.id in lines[2] + assert 'origin' in lines[2] + assert 'eu-west-1:{}'.format(released_image.id) in lines[2] + + assert released_image.id in lines[1] + assert 'origin' not in lines[1] + assert 'eu-west-1:{}'.format(base_image.id) in lines[1] + def test_list_quiet(self, base_image, released_image): r = runner.invoke(shipami, ['list', '-q']) @@ -187,6 +201,30 @@ def test_copy(self, ec2, base_image): assert image.name == base_image.name assert sorted(image.tags, key=lambda _: _['Key']) == sorted(expected_tags, key=lambda _: _['Key']) + def test_copy_aliased(self, ec2, base_image): + image_number = len(ec2.meta.client.describe_images()['Images']) + + expected_tags = [ + { + 'Key': 'shipami:managed', + 'Value': 'True' + }, + { + 'Key': 'shipami:copied_from', + 'Value': 'eu-west-1:{}'.format(base_image.id) + } + ] + + r = runner.invoke(shipami, ['cp', base_image.id]) + + returned_image_id = r.output.strip() + image = ec2.Image(returned_image_id) + + assert r.exit_code == 0 + assert len(ec2.meta.client.describe_images()['Images']) == image_number + 1 + assert image.name == base_image.name + assert sorted(image.tags, key=lambda _: _['Key']) == sorted(expected_tags, key=lambda _: _['Key']) + def test_copy_wait(self, ec2, base_image): image_number = len(ec2.meta.client.describe_images()['Images']) @@ -275,6 +313,16 @@ def test_delete(self, ec2, copied_image): assert len(ec2.meta.client.describe_images()['Images']) == 1 assert returned_image_id == copied_image_id + def test_delete_aliased(self, ec2, copied_image): + copied_image_id = copied_image.id + r = runner.invoke(shipami, ['rm', copied_image_id]) + + returned_image_id = r.output.strip() + + assert r.exit_code == 0 + assert len(ec2.meta.client.describe_images()['Images']) == 1 + assert returned_image_id == copied_image_id + def test_delete_not_managed(self, ec2, base_image): base_image_id = base_image.id r = runner.invoke(shipami, ['delete', base_image_id])