Ecs service force new deployment (#47983)
* Support UpdateService forceNewDeployment in ecs_service module * Force update to be called if force_new_deployment set * Fixes for review * Add force_new_deployment option to ecs_service.py cherrypicks changes from via/ansible Adds tests for pull request #42518 fixes backwards compatability with boto<1.8.4 * change version_added to 2.8 for force_new_deployment * remove extra lines from test * remove more unnecessary whitespace
This commit is contained in:
parent
3143abc8dc
commit
4b2356ff55
4 changed files with 251 additions and 6 deletions
|
@ -82,6 +82,12 @@ options:
|
||||||
- The number of times to check that the service is available
|
- The number of times to check that the service is available
|
||||||
required: false
|
required: false
|
||||||
default: 10
|
default: 10
|
||||||
|
force_new_deployment:
|
||||||
|
description:
|
||||||
|
- Force deployment of service even if there are no changes
|
||||||
|
required: false
|
||||||
|
version_added: 2.8
|
||||||
|
type: bool
|
||||||
deployment_configuration:
|
deployment_configuration:
|
||||||
description:
|
description:
|
||||||
- Optional parameters that control the deployment_configuration; format is '{"maximum_percent":<integer>, "minimum_healthy_percent":<integer>}
|
- Optional parameters that control the deployment_configuration; format is '{"maximum_percent":<integer>, "minimum_healthy_percent":<integer>}
|
||||||
|
@ -412,18 +418,20 @@ class EcsServiceManager:
|
||||||
return self.jsonize(response['service'])
|
return self.jsonize(response['service'])
|
||||||
|
|
||||||
def update_service(self, service_name, cluster_name, task_definition,
|
def update_service(self, service_name, cluster_name, task_definition,
|
||||||
desired_count, deployment_configuration, network_configuration, health_check_grace_period_seconds):
|
desired_count, deployment_configuration, network_configuration,
|
||||||
|
health_check_grace_period_seconds, force_new_deployment):
|
||||||
params = dict(
|
params = dict(
|
||||||
cluster=cluster_name,
|
cluster=cluster_name,
|
||||||
service=service_name,
|
service=service_name,
|
||||||
taskDefinition=task_definition,
|
taskDefinition=task_definition,
|
||||||
desiredCount=desired_count,
|
desiredCount=desired_count,
|
||||||
deploymentConfiguration=deployment_configuration
|
deploymentConfiguration=deployment_configuration)
|
||||||
)
|
|
||||||
if network_configuration:
|
if network_configuration:
|
||||||
params['networkConfiguration'] = network_configuration
|
params['networkConfiguration'] = network_configuration
|
||||||
if self.health_check_setable(params):
|
if self.health_check_setable(params):
|
||||||
params['healthCheckGracePeriodSeconds'] = health_check_grace_period_seconds
|
params['healthCheckGracePeriodSeconds'] = health_check_grace_period_seconds
|
||||||
|
if force_new_deployment:
|
||||||
|
params['forceNewDeployment'] = force_new_deployment
|
||||||
response = self.ecs.update_service(**params)
|
response = self.ecs.update_service(**params)
|
||||||
return self.jsonize(response['service'])
|
return self.jsonize(response['service'])
|
||||||
|
|
||||||
|
@ -472,6 +480,7 @@ def main():
|
||||||
role=dict(required=False, default='', type='str'),
|
role=dict(required=False, default='', type='str'),
|
||||||
delay=dict(required=False, type='int', default=10),
|
delay=dict(required=False, type='int', default=10),
|
||||||
repeat=dict(required=False, type='int', default=10),
|
repeat=dict(required=False, type='int', default=10),
|
||||||
|
force_new_deployment=dict(required=False, default=False, type='bool'),
|
||||||
deployment_configuration=dict(required=False, default={}, type='dict'),
|
deployment_configuration=dict(required=False, default={}, type='dict'),
|
||||||
placement_constraints=dict(required=False, default=[], type='list'),
|
placement_constraints=dict(required=False, default=[], type='list'),
|
||||||
placement_strategy=dict(required=False, default=[], type='list'),
|
placement_strategy=dict(required=False, default=[], type='list'),
|
||||||
|
@ -513,6 +522,9 @@ def main():
|
||||||
if module.params['launch_type']:
|
if module.params['launch_type']:
|
||||||
if not module.botocore_at_least('1.8.4'):
|
if not module.botocore_at_least('1.8.4'):
|
||||||
module.fail_json(msg='botocore needs to be version 1.8.4 or higher to use launch_type')
|
module.fail_json(msg='botocore needs to be version 1.8.4 or higher to use launch_type')
|
||||||
|
if module.params['force_new_deployment']:
|
||||||
|
if not module.botocore_at_least('1.8.4'):
|
||||||
|
module.fail_json(msg='botocore needs to be version 1.8.4 or higher to use force_new_deployment')
|
||||||
|
|
||||||
if module.params['state'] == 'present':
|
if module.params['state'] == 'present':
|
||||||
|
|
||||||
|
@ -520,7 +532,9 @@ def main():
|
||||||
update = False
|
update = False
|
||||||
|
|
||||||
if existing and 'status' in existing and existing['status'] == "ACTIVE":
|
if existing and 'status' in existing and existing['status'] == "ACTIVE":
|
||||||
if service_mgr.is_matching_service(module.params, existing):
|
if module.params['force_new_deployment']:
|
||||||
|
update = True
|
||||||
|
elif service_mgr.is_matching_service(module.params, existing):
|
||||||
matching = True
|
matching = True
|
||||||
results['service'] = existing
|
results['service'] = existing
|
||||||
else:
|
else:
|
||||||
|
@ -552,8 +566,8 @@ def main():
|
||||||
module.params['desired_count'],
|
module.params['desired_count'],
|
||||||
deploymentConfiguration,
|
deploymentConfiguration,
|
||||||
network_configuration,
|
network_configuration,
|
||||||
module.params['health_check_grace_period_seconds']
|
module.params['health_check_grace_period_seconds'],
|
||||||
)
|
module.params['force_new_deployment'])
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
response = service_mgr.create_service(module.params['name'],
|
response = service_mgr.create_service(module.params['name'],
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
- hosts: localhost
|
||||||
|
connection: local
|
||||||
|
vars:
|
||||||
|
resource_prefix: 'ansible-testing-fnd'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- block:
|
||||||
|
- name: set up aws connection info
|
||||||
|
set_fact:
|
||||||
|
aws_connection_info: &aws_connection_info
|
||||||
|
aws_access_key: "{{ aws_access_key }}"
|
||||||
|
aws_secret_key: "{{ aws_secret_key }}"
|
||||||
|
security_token: "{{ security_token }}"
|
||||||
|
region: "{{ aws_region }}"
|
||||||
|
no_log: True
|
||||||
|
|
||||||
|
- name: create ecs cluster
|
||||||
|
ecs_cluster:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
|
||||||
|
- name: create ecs_taskdefinition
|
||||||
|
ecs_taskdefinition:
|
||||||
|
containers:
|
||||||
|
- name: my_container
|
||||||
|
image: ubuntu
|
||||||
|
memory: 128
|
||||||
|
family: "{{ resource_prefix }}"
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: ecs_taskdefinition_creation
|
||||||
|
|
||||||
|
- name: create ecs_service
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 1
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: ecs_service_creation
|
||||||
|
|
||||||
|
- name: ecs_service works fine even when older botocore is used
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- ecs_service_creation.changed
|
||||||
|
|
||||||
|
- name: create ecs_service using force_new_deployment
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 1
|
||||||
|
force_new_deployment: true
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: ecs_service_creation_force_new_deploy
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: check that module returns success
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- ecs_service_creation_force_new_deploy.changed
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: scale down ecs service
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 0
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: pause to wait for scale down
|
||||||
|
pause:
|
||||||
|
seconds: 30
|
||||||
|
|
||||||
|
- name: remove ecs service
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 1
|
||||||
|
state: absent
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: remove ecs task definition
|
||||||
|
ecs_taskdefinition:
|
||||||
|
containers:
|
||||||
|
- name: my_container
|
||||||
|
image: ubuntu
|
||||||
|
memory: 128
|
||||||
|
family: "{{ resource_prefix }}"
|
||||||
|
revision: "{{ ecs_taskdefinition_creation.taskdefinition.revision }}"
|
||||||
|
state: absent
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: remove ecs cluster
|
||||||
|
ecs_cluster:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
state: absent
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
|
@ -0,0 +1,109 @@
|
||||||
|
- hosts: localhost
|
||||||
|
connection: local
|
||||||
|
vars:
|
||||||
|
resource_prefix: 'ansible-testing-fndf'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- block:
|
||||||
|
- name: set up aws connection info
|
||||||
|
set_fact:
|
||||||
|
aws_connection_info: &aws_connection_info
|
||||||
|
aws_access_key: "{{ aws_access_key }}"
|
||||||
|
aws_secret_key: "{{ aws_secret_key }}"
|
||||||
|
security_token: "{{ security_token }}"
|
||||||
|
region: "{{ aws_region }}"
|
||||||
|
no_log: True
|
||||||
|
|
||||||
|
- name: create ecs cluster
|
||||||
|
ecs_cluster:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
|
||||||
|
- name: create ecs_taskdefinition
|
||||||
|
ecs_taskdefinition:
|
||||||
|
containers:
|
||||||
|
- name: my_container
|
||||||
|
image: ubuntu
|
||||||
|
memory: 128
|
||||||
|
family: "{{ resource_prefix }}"
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: ecs_taskdefinition_creation
|
||||||
|
|
||||||
|
- name: create ecs_service
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 1
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: ecs_service_creation
|
||||||
|
|
||||||
|
- name: ecs_service works fine even when older botocore is used
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- ecs_service_creation.changed
|
||||||
|
|
||||||
|
- name: create ecs_service using force_new_deployment
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 1
|
||||||
|
force_new_deployment: true
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
register: ecs_service_creation_force_new_deploy
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: check that graceful failure message is returned from ecs_service
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- ecs_service_creation_force_new_deploy.failed
|
||||||
|
- 'ecs_service_creation_force_new_deploy.msg == "botocore needs to be version 1.8.4 or higher to use force_new_deployment"'
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: scale down ecs service
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 0
|
||||||
|
state: present
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: pause to wait for scale down
|
||||||
|
pause:
|
||||||
|
seconds: 30
|
||||||
|
|
||||||
|
- name: remove ecs service
|
||||||
|
ecs_service:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
cluster: "{{ resource_prefix }}"
|
||||||
|
task_definition: "{{ resource_prefix }}"
|
||||||
|
desired_count: 1
|
||||||
|
state: absent
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: remove ecs task definition
|
||||||
|
ecs_taskdefinition:
|
||||||
|
containers:
|
||||||
|
- name: my_container
|
||||||
|
image: ubuntu
|
||||||
|
memory: 128
|
||||||
|
family: "{{ resource_prefix }}"
|
||||||
|
revision: "{{ ecs_taskdefinition_creation.taskdefinition.revision }}"
|
||||||
|
state: absent
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: remove ecs cluster
|
||||||
|
ecs_cluster:
|
||||||
|
name: "{{ resource_prefix }}"
|
||||||
|
state: absent
|
||||||
|
<<: *aws_connection_info
|
||||||
|
ignore_errors: yes
|
|
@ -25,6 +25,20 @@ source "${MYTMPDIR}/botocore-1.7.44/bin/activate"
|
||||||
$PYTHON -m pip install 'botocore>=1.7.44,<1.8.4' boto3
|
$PYTHON -m pip install 'botocore>=1.7.44,<1.8.4' boto3
|
||||||
ansible-playbook -i ../../inventory -e @../../integration_config.yml -e @../../cloud-config-aws.yml -v playbooks/network_assign_public_ip_fail.yml "$@"
|
ansible-playbook -i ../../inventory -e @../../integration_config.yml -e @../../cloud-config-aws.yml -v playbooks/network_assign_public_ip_fail.yml "$@"
|
||||||
|
|
||||||
|
# Test graceful failure for force new deployment #42518
|
||||||
|
# applies for botocore < 1.8.4
|
||||||
|
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/botocore-1.8.4"
|
||||||
|
source "${MYTMPDIR}/botocore-1.8.4/bin/activate"
|
||||||
|
$PYTHON -m pip install 'botocore>=1.7.44,<1.8.4' boto3
|
||||||
|
ansible-playbook -i ../../inventory -e @../../integration_config.yml -e @../../cloud-config-aws.yml -v playbooks/network_force_new_deployment_fail.yml "$@"
|
||||||
|
|
||||||
|
# Test force new deployment #42518
|
||||||
|
# applies for botocore < 1.8.4
|
||||||
|
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/botocore-1.8.5"
|
||||||
|
source "${MYTMPDIR}/botocore-1.8.5/bin/activate"
|
||||||
|
$PYTHON -m pip install 'botocore>1.8.4' boto3
|
||||||
|
ansible-playbook -i ../../inventory -e @../../integration_config.yml -e @../../cloud-config-aws.yml -v playbooks/network_force_new_deployment.yml "$@"
|
||||||
|
|
||||||
# Run full test suite
|
# Run full test suite
|
||||||
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/botocore-recent"
|
virtualenv --system-site-packages --python "${PYTHON}" "${MYTMPDIR}/botocore-recent"
|
||||||
source "${MYTMPDIR}/botocore-recent/bin/activate"
|
source "${MYTMPDIR}/botocore-recent/bin/activate"
|
||||||
|
|
Loading…
Reference in a new issue