From f9b53e14ce9464ccabd5c1f3c9741c53f252155b Mon Sep 17 00:00:00 2001 From: Maks3w Date: Tue, 12 Feb 2019 23:16:35 +0100 Subject: [PATCH] [run] Override image, tag or role --- ecs_deploy/cli.py | 17 ++++++++-- tests/test_cli.py | 84 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/ecs_deploy/cli.py b/ecs_deploy/cli.py index fb9b194..1a3f0da 100644 --- a/ecs_deploy/cli.py +++ b/ecs_deploy/cli.py @@ -296,9 +296,12 @@ def scale(cluster, service, desired_count, access_key_id, secret_access_key, reg @click.argument('cluster') @click.argument('task') @click.argument('count', required=False, default=1) +@click.option('-t', '--tag', help='Changes the tag for ALL container images') +@click.option('-i', '--image', type=(str, str), multiple=True, help='Overwrites the image for a container: ') @click.option('-c', '--command', type=(str, str), multiple=True, help='Overwrites the command in a container: ') @click.option('-e', '--env', type=(str, str, str), multiple=True, help='Adds or changes an environment variable: ') @click.option('-s', '--secret', type=(str, str, str), multiple=True, help='Adds or changes a secret environment variable from the AWS Parameter Store (Not available for Fargate): ') +@click.option('-r', '--role', type=str, help='Sets the task\'s role ARN: ') @click.option('--launchtype', type=click.Choice([LAUNCH_TYPE_EC2, LAUNCH_TYPE_FARGATE]), default=LAUNCH_TYPE_EC2, help='ECS Launch type (default: EC2)') @click.option('--subnet', type=str, multiple=True, help='A subnet ID to launch the task within. Required for launch type FARGATE (multiple values possible)') @click.option('--securitygroup', type=str, multiple=True, help='A security group ID to launch the task within. Required for launch type FARGATE (multiple values possible)') @@ -310,7 +313,8 @@ def scale(cluster, service, desired_count, access_key_id, secret_access_key, reg @click.option('--diff/--no-diff', default=True, help='Print what values were changed in the task definition') @click.option('--exclusive-env', is_flag=True, default=False, help='Set the given environment variables exclusively and remove all other pre-existing env variables from all containers') @click.option('--exclusive-secrets', is_flag=True, default=False, help='Set the given secrets exclusively and remove all other pre-existing secrets from all containers') -def run(cluster, task, count, command, env, secret, launchtype, subnet, securitygroup, public_ip, region, access_key_id, secret_access_key, profile, diff, exclusive_env, exclusive_secrets): +@click.option('--deregister/--no-deregister', default=True, help='Deregister or keep the old task definition (default: --deregister)') +def run(cluster, task, count, tag, image, command, env, secret, role, launchtype, subnet, securitygroup, public_ip, region, access_key_id, secret_access_key, profile, diff, exclusive_env, exclusive_secrets, deregister): """ Run a one-off task. @@ -319,18 +323,24 @@ def run(cluster, task, count, command, env, secret, launchtype, subnet, security TASK is the name of your task definition (e.g. 'my-task') within ECS. COUNT is the number of tasks your service should run. """ + should_create_task_definition = image or tag or role try: client = get_client(access_key_id, secret_access_key, region, profile) action = RunAction(client, cluster) - td = action.get_task_definition(task) + td = td_old = action.get_task_definition(task) + td.set_images(tag, **{key: value for (key, value) in image}) td.set_commands(**{key: value for (key, value) in command}) td.set_environment(env, exclusive_env) td.set_secrets(secret, exclusive_secrets) + td.set_role_arn(role) if diff: print_diff(td, 'Using task definition: %s' % task) + if should_create_task_definition: + td = create_task_definition(action, td) + action.run(td, count, 'ECS Deploy', launchtype, subnet, securitygroup, public_ip) click.secho( @@ -345,6 +355,9 @@ def run(cluster, task, count, command, env, secret, launchtype, subnet, security click.secho('- %s' % started_task['taskArn'], fg='green') click.secho(' ') + if should_create_task_definition and deregister: + deregister_task_definition(action, td_old) + except EcsError as e: click.secho('%s\n' % str(e), fg='red', err=True) exit(1) diff --git a/tests/test_cli.py b/tests/test_cli.py index 939d6ab..569e2cd 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -623,20 +623,98 @@ def test_run_task(get_client, runner): assert result.exit_code == 0 assert u"Successfully started 2 instances of task: test-task:2" in result.output + assert u'Successfully deregistered revision: 2' not in result.output assert u"- arn:foo:bar" in result.output assert u"- arn:lorem:ipsum" in result.output @patch('ecs_deploy.cli.get_client') -def test_run_task_with_command(get_client, runner): +def test_run_with_role_arn_deregister_old_task_definiion(get_client, runner): get_client.return_value = EcsTestClient('acces_key', 'secret_key') - result = runner.invoke(cli.run, (CLUSTER_NAME, 'test-task', '2', '-c', 'webserver', 'date')) + result = runner.invoke(cli.run, (CLUSTER_NAME, 'test-task:1', '2', '-r', 'arn:new:role')) + assert result.exit_code == 0 + assert not result.exception + assert u"Using task definition: test-task" in result.output + assert u'Changed role_arn to: "arn:new:role" (was: "arn:test:role:1")' in result.output + assert u"Creating new task definition revision" in result.output + assert u'Successfully created revision: 2' in result.output + assert u"Successfully started 2 instances of task: test-task:2" in result.output + assert u'Successfully deregistered revision: 1' in result.output + assert u"- arn:foo:bar" in result.output + assert u"- arn:lorem:ipsum" in result.output + +@patch('ecs_deploy.cli.get_client') +def test_run_with_role_arn_keep_old_task_definiion(get_client, runner): + get_client.return_value = EcsTestClient('acces_key', 'secret_key') + result = runner.invoke(cli.run, (CLUSTER_NAME, 'test-task:1', '2', '-r', 'arn:new:role', '--no-deregister')) + assert result.exit_code == 0 assert not result.exception + assert u"Using task definition: test-task" in result.output + assert u'Changed role_arn to: "arn:new:role" (was: "arn:test:role:1")' in result.output + assert u"Creating new task definition revision" in result.output + assert u'Successfully created revision: 2' in result.output + assert u"Successfully started 2 instances of task: test-task:2" in result.output + assert u'Successfully deregistered revision: 1' not in result.output + assert u"- arn:foo:bar" in result.output + assert u"- arn:lorem:ipsum" in result.output + + +@patch('ecs_deploy.cli.get_client') +def test_run_new_tag(get_client, runner): + get_client.return_value = EcsTestClient('acces_key', 'secret_key') + result = runner.invoke(cli.run, (CLUSTER_NAME, 'test-task', '2', '-t', 'latest')) assert result.exit_code == 0 + assert not result.exception + assert u"Using task definition: test-task" in result.output + assert u"Creating new task definition revision" in result.output + assert u'Changed image of container "webserver" to: "webserver:latest" (was: "webserver:123")' in result.output + assert u'Changed image of container "application" to: "application:latest" (was: "application:123")' in result.output + assert u'Successfully created revision: 2' in result.output + assert u"Successfully started 2 instances of task: test-task:2" in result.output + assert u"- arn:foo:bar" in result.output + assert u"- arn:lorem:ipsum" in result.output + +@patch('ecs_deploy.cli.get_client') +def test_run_one_new_image(get_client, runner): + get_client.return_value = EcsTestClient('acces_key', 'secret_key') + result = runner.invoke(cli.run, (CLUSTER_NAME, 'test-task', '2', '-i', 'application', 'application:latest')) + assert result.exit_code == 0 + assert not result.exception + assert u"Using task definition: test-task" in result.output + assert u"Creating new task definition revision" in result.output + assert u'Changed image of container "application" to: "application:latest" (was: "application:123")' in result.output + assert u'Successfully created revision: 2' in result.output + assert u"Successfully started 2 instances of task: test-task:2" in result.output + assert u"- arn:foo:bar" in result.output + assert u"- arn:lorem:ipsum" in result.output + + +@patch('ecs_deploy.cli.get_client') +def test_run_two_new_images(get_client, runner): + get_client.return_value = EcsTestClient('acces_key', 'secret_key') + result = runner.invoke(cli.run, (CLUSTER_NAME, 'test-task', '2', '-i', 'application', 'application:latest', + '-i', 'webserver', 'webserver:latest')) + assert result.exit_code == 0 + assert not result.exception + assert u"Using task definition: test-task" in result.output + assert u"Creating new task definition revision" in result.output + assert u'Changed image of container "webserver" to: "webserver:latest" (was: "webserver:123")' in result.output + assert u'Changed image of container "application" to: "application:latest" (was: "application:123")' in result.output + assert u"Successfully started 2 instances of task: test-task:2" in result.output + assert u"- arn:foo:bar" in result.output + assert u"- arn:lorem:ipsum" in result.output + + +@patch('ecs_deploy.cli.get_client') +def test_run_one_new_command(get_client, runner): + get_client.return_value = EcsTestClient('acces_key', 'secret_key') + result = runner.invoke(cli.run, (CLUSTER_NAME, 'test-task', '2', '-c', 'application', 'date')) + assert result.exit_code == 0 + assert not result.exception assert u"Using task definition: test-task" in result.output - assert u'Changed command of container "webserver" to: "date" (was: "run")' in result.output + assert u'Changed command of container "application" to: "date" (was: "run")' in result.output assert u"Successfully started 2 instances of task: test-task:2" in result.output assert u"- arn:foo:bar" in result.output assert u"- arn:lorem:ipsum" in result.output