From 80c9c7d2682efcf073b55466cd796b979e2764b4 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 08:34:16 +0000 Subject: [PATCH] ecs_service - support setting deployment controller on a service (#340) (#1303) [PR #340/c9b1b02e backport][stable-4] ecs_service - support setting deployment controller on a service This is a backport of PR #340 as merged into main (c9b1b02). SUMMARY Support setting platform version to 1.4.0 (LATEST is 1.3.0) and deployment controller. The first allows access to new 1.4.0 features. The second change allows you to create a service that can be controlled with Code Deploy. Example: - name: create a Fargate service community.aws.ecs_service: state: present name: "my-service" cluster: "my-cluster" platform_version: 1.4.0 task_definition: "my-task" desired_count: "1" launch_type: FARGATE scheduling_strategy: REPLICA deployment_controller: type: CODE_DEPLOY load_balancers: - targetGroupArn: "arn:..." containerName: example containerPort: 80 network_configuration: subnets: - "{{vpc_zone_a.subnet.id}}" - "{{vpc_zone_b.subnet.id}}" security_groups: - "sg-example" assign_public_ip: true This fixes #338. ISSUE TYPE Feature Pull Request Reviewed-by: Mark Chappell --- .../fragments/340-deployment-controller.yml | 2 + plugins/modules/ecs_service.py | 59 +++++++++++++++---- 2 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 changelogs/fragments/340-deployment-controller.yml diff --git a/changelogs/fragments/340-deployment-controller.yml b/changelogs/fragments/340-deployment-controller.yml new file mode 100644 index 00000000000..ac6330b0f18 --- /dev/null +++ b/changelogs/fragments/340-deployment-controller.yml @@ -0,0 +1,2 @@ +minor_changes: +- ecs_service - added parameter ``deployment_controller`` so service can be controlled by Code Deploy (https://github.com/ansible-collections/community.aws/pull/340). diff --git a/plugins/modules/ecs_service.py b/plugins/modules/ecs_service.py index aa455d72345..78e352447ee 100644 --- a/plugins/modules/ecs_service.py +++ b/plugins/modules/ecs_service.py @@ -12,16 +12,16 @@ version_added: 1.0.0 short_description: Create, terminate, start or stop a service in ECS description: - - Creates or terminates ECS. services. + - Creates or terminates ECS services. notes: - The service role specified must be assumable. (i.e. have a trust relationship for the ecs service, ecs.amazonaws.com) - For details of the parameters and returns see U(https://boto3.readthedocs.io/en/latest/reference/services/ecs.html). - An IAM role must have been previously created. author: - - "Mark Chance (@Java1Guy)" - - "Darek Kaczynski (@kaczynskid)" - - "Stephane Maarek (@simplesteph)" - - "Zac Blazic (@zacblazic)" + - "Mark Chance (@Java1Guy)" + - "Darek Kaczynski (@kaczynskid)" + - "Stephane Maarek (@simplesteph)" + - "Zac Blazic (@zacblazic)" options: state: description: @@ -46,11 +46,15 @@ description: - The task definition the service will run. - This parameter is required when I(state=present). + - This parameter is ignored when updating a service with a C(CODE_DEPLOY) deployment controller in which case + the task definition is managed by Code Pipeline and cannot be updated. required: false type: str load_balancers: description: - The list of ELBs defined for this service. + - Load balancers for an existing service cannot be updated, and it is an error to do so. + - When the deployment controller is CODE_DEPLOY changes to this value are simply ignored, and do not cause an error. required: false type: list elements: dict @@ -90,6 +94,17 @@ required: false type: bool default: false + deployment_controller: + description: + - The deployment controller to use for the service. If no deploymenet controller is specified, the ECS controller is used. + required: false + version_added: 4.1.0 + type: dict + suboptions: + type: + type: str + choices: ["ECS", "CODE_DEPLOY", "EXTERNAL"] + description: The deployment controller type to use. deployment_configuration: description: - Optional parameters that control the deployment_configuration. @@ -238,9 +253,8 @@ default: false version_added: 4.1.0 extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 - + - amazon.aws.aws + - amazon.aws.ec2 ''' EXAMPLES = r''' @@ -590,6 +604,10 @@ ''' import time +DEPLOYMENT_CONTROLLER_TYPE_MAP = { + 'type': 'str', +} + DEPLOYMENT_CONFIGURATION_TYPE_MAP = { 'maximum_percent': 'int', 'minimum_healthy_percent': 'int', @@ -664,7 +682,8 @@ def is_matching_service(self, expected, existing): # but the user is just entering # ansible-fargate-nginx:3 if expected['task_definition'] != existing['taskDefinition'].split('/')[-1]: - return False + if existing['deploymentController']['type'] != 'CODE_DEPLOY': + return False if expected.get('health_check_grace_period_seconds'): if expected.get('health_check_grace_period_seconds') != existing.get('healthCheckGracePeriodSeconds'): @@ -682,7 +701,7 @@ def is_matching_service(self, expected, existing): return True def create_service(self, service_name, cluster_name, task_definition, load_balancers, - desired_count, client_token, role, deployment_configuration, + desired_count, client_token, role, deployment_controller, deployment_configuration, placement_constraints, placement_strategy, health_check_grace_period_seconds, network_configuration, service_registries, launch_type, platform_version, scheduling_strategy, capacity_provider_strategy): @@ -699,6 +718,8 @@ def create_service(self, service_name, cluster_name, task_definition, load_balan ) if network_configuration: params['networkConfiguration'] = network_configuration + if deployment_controller: + params['deploymentController'] = deployment_controller if launch_type: params['launchType'] = launch_type if platform_version: @@ -786,6 +807,7 @@ def main(): repeat=dict(required=False, type='int', default=10), force_new_deployment=dict(required=False, default=False, type='bool'), force_deletion=dict(required=False, default=False, type='bool'), + deployment_controller=dict(required=False, default={}, type='dict'), deployment_configuration=dict(required=False, default={}, type='dict'), wait=dict(required=False, default=False, type='bool'), placement_constraints=dict( @@ -851,6 +873,11 @@ def main(): else: network_configuration = None + deployment_controller = map_complex_type(module.params['deployment_controller'], + DEPLOYMENT_CONTROLLER_TYPE_MAP) + + deploymentController = snake_dict_to_camel_dict(deployment_controller) + deployment_configuration = map_complex_type(module.params['deployment_configuration'], DEPLOYMENT_CONFIGURATION_TYPE_MAP) @@ -912,12 +939,19 @@ def main(): if 'capacityProviderStrategy' in existing.keys(): module.fail_json(msg="It is not possible to change an existing service from capacity_provider_strategy to launch_type.") if (existing['loadBalancers'] or []) != loadBalancers: - module.fail_json(msg="It is not possible to update the load balancers of an existing service") + if existing['deploymentController']['type'] != 'CODE_DEPLOY': + module.fail_json(msg="It is not possible to update the load balancers of an existing service") + + if existing.get('deploymentController', {}).get('type', None) == 'CODE_DEPLOY': + task_definition = '' + network_configuration = [] + else: + task_definition = module.params['task_definition'] # update required response = service_mgr.update_service(module.params['name'], module.params['cluster'], - module.params['task_definition'], + task_definition, module.params['desired_count'], deploymentConfiguration, network_configuration, @@ -935,6 +969,7 @@ def main(): module.params['desired_count'], clientToken, role, + deploymentController, deploymentConfiguration, module.params['placement_constraints'], module.params['placement_strategy'],