This repository was archived by the owner on Oct 8, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathaction-create.yml
More file actions
354 lines (321 loc) · 16 KB
/
action-create.yml
File metadata and controls
354 lines (321 loc) · 16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
---
# Build and ship a container image
- name: Build and push a Docker image.
when: deploy_container.create_image
block:
- name: Create Dockerfile from template.
ansible.builtin.template:
src: "{{ deploy_container.dockerfile_template }}"
dest: "{{ deploy_container.docker_build_dir }}/Dockerfile"
delegate_to: localhost
- name: Set Docker registry username and password.
ansible.builtin.set_fact:
_docker_registry_username: "{{ deploy_container.docker_registry_user }}"
_docker_registry_password: "{{ deploy_container.docker_registry_pass }}"
delegate_to: localhost
- name: AWS ECR handling.
when: deploy_container.aws_ecr.enabled
delegate_to: localhost
block:
- name: Fetch AWS ECR registry login token. # token valid for 12 hours
ansible.builtin.command:
cmd: "aws ecr get-login-password --region {{ deploy_container.aws_ecr.region }} --profile {{ deploy_container.aws_ecr.aws_profile }}"
register: _docker_registry_ecr_token
- name: Set AWS ECR registry password.
ansible.builtin.set_fact:
_docker_registry_password: "{{ _docker_registry_ecr_token.stdout }}"
- name: Set AWS ECR registry username.
ansible.builtin.set_fact:
_docker_registry_username: "AWS"
- name: Remove Docker credentials file.
ansible.builtin.file:
state: absent
path: "/home/{{ deploy_user }}/.docker/config.json"
delegate_to: localhost
- name: Log into Docker registry.
community.docker.docker_login:
registry_url: "{{ deploy_container.docker_registry_url }}"
username: "{{ _docker_registry_username }}"
password: "{{ _docker_registry_password }}"
reauthorize: true
delegate_to: localhost
- name: Build and push container image.
community.docker.docker_image:
build:
path: "{{ deploy_container.docker_build_dir }}"
name: "{{ deploy_container.docker_registry_name }}/{{ deploy_container.container_name }}"
tag: "{{ deploy_container.container_tag | default('latest') }}"
push: true
source: build
force_source: "{{ deploy_container.container_force_build }}"
force_tag: "{{ deploy_container.container_force_build }}"
delegate_to: localhost
# AWS specific things start here
- name: Fetch the ACM role from ce-provision if required.
when: deploy_container.aws_ecs.acm.create_cert
delegate_to: localhost
block:
- name: Ensure the aws_acm directory exists.
ansible.builtin.file:
path: "{{ _ce_deploy_base_dir }}/roles/aws_acm/{{ item }}"
state: directory
mode: '0755'
with_items:
- tasks
- defaults
- name: Fetch the aws_acm files.
ansible.builtin.get_url:
url: "https://raw.githubusercontent.com/codeenigma/ce-provision/{{ deploy_container.ce_provision_version }}/roles/aws/aws_acm/{{ item }}/main.yml"
dest: "{{ _ce_deploy_base_dir }}/roles/aws_acm/{{ item }}/main.yml"
with_items:
- tasks
- defaults
- name: Fetch the aws_acm tasks.
ansible.builtin.get_url:
url: "https://raw.githubusercontent.com/codeenigma/ce-provision/{{ deploy_container.ce_provision_version }}/roles/aws/aws_acm/tasks/main.yml"
dest: "{{ _ce_deploy_base_dir }}/roles/aws_acm/tasks/main.yml"
# Gather all network information and set up task definition
- name: Network handling and task definition creation.
when: deploy_container.aws_ecs.enabled
block:
- name: Gather VPC information.
amazon.aws.ec2_vpc_net_info:
profile: "{{ deploy_container.aws_ecs.aws_profile }}"
region: "{{ deploy_container.aws_ecs.region }}"
filters:
"tag:Name": "{{ deploy_container.aws_ecs.vpc_name }}"
register: _aws_ecs_cluster_vpc
delegate_to: localhost
when:
- deploy_container.aws_ecs.vpc_name is defined
- deploy_container.aws_ecs.vpc_name | length > 0
- name: Set the VPC id from name.
ansible.builtin.set_fact:
_aws_ecs_cluster_vpc_id: "{{ _aws_ecs_cluster_vpc.vpcs[0].vpc_id }}"
when:
- deploy_container.aws_ecs.vpc_name is defined
- deploy_container.aws_ecs.vpc_name | length > 0
- name: Use provided VPC id.
ansible.builtin.set_fact:
_aws_ecs_cluster_vpc_id: "{{ deploy_container.aws_ecs.vpc_id }}"
when: deploy_container.aws_ecs.vpc_name is not defined or (deploy_container.aws_ecs.vpc_name | length) == 0
- name: Reset subnets lists.
ansible.builtin.set_fact:
_aws_ecs_cluster_public_subnets_ids: []
_aws_ecs_cluster_private_subnets_ids: []
- name: Construct list of public subnet IDs.
ansible.builtin.include_tasks: subnet-public.yml
with_items: "{{ deploy_container.aws_ecs.elb_subnets }}"
loop_control:
loop_var: subnet
- name: Construct list of private subnet IDs.
ansible.builtin.include_tasks: subnet-private.yml
with_items: "{{ deploy_container.aws_ecs.service_subnets }}"
loop_control:
loop_var: subnet
- name: Set task definition name.
ansible.builtin.set_fact:
_aws_ecs_service_task_definition: "{{ deploy_container.aws_ecs.family_name }}"
- name: Set task definition revision if applicable.
ansible.builtin.set_fact:
_aws_ecs_service_task_definition: "{{ deploy_container.aws_ecs.family_name }}:{{ deploy_container.aws_ecs.task_definition_revision }}"
when:
- deploy_container.aws_ecs.task_definition_revision | length > 0
- name: Create task definition.
community.aws.ecs_taskdefinition:
region: "{{ deploy_container.aws_ecs.region }}"
profile: "{{ deploy_container.aws_ecs.aws_profile }}"
family: "{{ deploy_container.aws_ecs.family_name }}"
execution_role_arn: "{{ deploy_container.aws_ecs.task_execution_role_arn }}"
task_role_arn: "{{ deploy_container.aws_ecs.task_role_arn | default(omit) }}"
containers: "{{ deploy_container.aws_ecs.containers }}"
launch_type: "{{ deploy_container.aws_ecs.launch_type }}"
cpu: "{{ deploy_container.aws_ecs.cpu | default(omit) }}"
memory: "{{ deploy_container.aws_ecs.memory | default(omit) }}"
state: present
network_mode: "{{ deploy_container.aws_ecs.network_mode }}"
volumes: "{{ deploy_container.aws_ecs.volumes | default(omit) }}"
force_create: "{{ deploy_container.aws_ecs.task_definition_force_create }}"
delegate_to: localhost
# Create load balancer and associated assets (not needed for standalone tasks)
- name: Web application service handling.
when:
- deploy_container.aws_ecs.service_type == 'web_app'
- deploy_container.aws_ecs.enabled
block:
- name: Create a target group with IP address targets.
community.aws.elb_target_group:
region: "{{ deploy_container.aws_ecs.region }}"
profile: "{{ deploy_container.aws_ecs.aws_profile }}"
name: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}" # 32 char limit
protocol: "{{ deploy_container.aws_ecs.target_group_protocol }}"
port: "{{ deploy_container.aws_ecs.target_group_port }}"
vpc_id: "{{ _aws_ecs_cluster_vpc_id }}"
health_check_protocol: "{{ deploy_container.aws_ecs.health_check.protocol }}"
health_check_path: "{{ deploy_container.aws_ecs.health_check.path }}"
health_check_interval: "{{ deploy_container.aws_ecs.health_check.interval | default(omit) }}"
healthy_threshold_count: "{{ deploy_container.aws_ecs.health_check.healthy_threshold_count | default(omit) }}"
deregistration_delay_timeout: "{{ deploy_container.aws_ecs.target_group_deregistration_delay_timeout }}"
unhealthy_threshold_count: "{{ deploy_container.aws_ecs.health_check.unhealthy_threshold_count | default(omit) }}"
successful_response_codes: "{{ deploy_container.aws_ecs.health_check.response_codes }}"
target_type: ip
targets: "{{ deploy_container.aws_ecs.targets }}"
state: present
wait_timeout: "{{ deploy_container.aws_ecs.target_group_wait_timeout }}"
wait: true
register: _aws_ecs_target_group
delegate_to: localhost
- name: Create SSL certificate for load balancer.
ansible.builtin.include_role:
name: aws_acm
vars:
aws_acm:
region: "{{ deploy_container.aws_ecs.region }}"
aws_profile: "{{ deploy_container.aws_ecs.aws_profile }}"
tags: "{{ deploy_container.aws_ecs.tags }}"
export: false
domain_name: "{{ deploy_container.aws_ecs.domain_name }}"
extra_domains: "{{ deploy_container.aws_ecs.acm.extra_domains }}"
route_53:
aws_profile: "{{ deploy_container.aws_ecs.route_53.aws_profile }}"
zone: "{{ deploy_container.aws_ecs.route_53.zone }}"
when:
- deploy_container.aws_ecs.acm.create_cert
- name: Default to provided SSL certificate ARN.
ansible.builtin.set_fact:
_ssl_certificate_arn: "{{ deploy_container.aws_ecs.ssl_certificate_arn }}"
- name: If provided, override SSL certificate ARN with the one received from ACM.
ansible.builtin.set_fact:
_ssl_certificate_arn: "{{ aws_acm_certificate_arn }}"
when:
- deploy_container.aws_ecs.acm.create_cert
- name: Define default ALB listeners.
ansible.builtin.set_fact:
_aws_ecs_cluster_listeners_http:
Protocol: HTTP
Port: "{{ deploy_container.aws_ecs.elb_http_port }}"
DefaultActions:
- Type: forward
TargetGroupName: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}"
Rules: "{{ deploy_container.aws_ecs.elb_listener_http_rules }}"
_aws_ecs_cluster_listeners_redirect:
Protocol: HTTP
Port: "{{ deploy_container.aws_ecs.elb_http_port }}"
DefaultActions:
- Type: redirect
RedirectConfig:
Protocol: HTTPS
Host: "#{host}"
Query: "#{query}"
Path: "/#{path}"
Port: "{{ deploy_container.aws_ecs.elb_https_port }}"
StatusCode: HTTP_301
_aws_ecs_cluster_listeners_https:
Protocol: HTTPS
Port: "{{ deploy_container.aws_ecs.elb_https_port }}"
SslPolicy: "{{ deploy_container.aws_ecs.elb_ssl_policy }}"
Certificates:
- CertificateArn: "{{ _ssl_certificate_arn }}"
DefaultActions:
- Type: forward
TargetGroupName: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}"
Rules: "{{ deploy_container.aws_ecs.elb_listener_https_rules }}"
- name: Add HTTP listeners.
ansible.builtin.set_fact:
_aws_ecs_cluster_listeners: "{{ [ _aws_ecs_cluster_listeners_http ] }}"
when:
- _ssl_certificate_arn | length < 1
- name: Add HTTPS Listener.
ansible.builtin.set_fact:
_aws_ecs_cluster_listeners: "{{ [ _aws_ecs_cluster_listeners_redirect, _aws_ecs_cluster_listeners_https ] }}"
when:
- _ssl_certificate_arn | length > 1
- name: Add custom Listeners.
ansible.builtin.set_fact:
_aws_ecs_cluster_listeners: "{{ _aws_ecs_cluster_listeners + deploy_container.aws_ecs.elb_listeners }}"
when:
- deploy_container.aws_ecs.elb_listeners is defined
- deploy_container.aws_ecs.elb_listeners | length
- name: Create an ALB.
amazon.aws.elb_application_lb:
region: "{{ deploy_container.aws_ecs.region }}"
profile: "{{ deploy_container.aws_ecs.aws_profile }}"
name: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}" # 32 char limit
state: present
tags: "{{ deploy_container.aws_ecs.tags }}"
subnets: "{{ _aws_ecs_cluster_public_subnets_ids }}"
security_groups: "{{ deploy_container.aws_ecs.elb_security_groups }}"
listeners: "{{ _aws_ecs_cluster_listeners }}"
idle_timeout: "{{ deploy_container.aws_ecs.elb_idle_timeout }}"
ip_address_type: "{{ deploy_container.aws_ecs.elb_ip_address_type }}"
wait: true
register: _aws_ecs_cluster_alb
delegate_to: localhost
- name: Create ECS service.
community.aws.ecs_service:
region: "{{ deploy_container.aws_ecs.region }}"
profile: "{{ deploy_container.aws_ecs.aws_profile }}"
state: present
name: "{{ deploy_container.aws_ecs.family_name }}"
cluster: "{{ deploy_container.aws_ecs.cluster_name }}"
task_definition: "{{ _aws_ecs_service_task_definition }}"
desired_count: "{{ deploy_container.aws_ecs.task_count }}"
launch_type: "{{ deploy_container.aws_ecs.launch_type }}"
platform_version: LATEST
load_balancers: # see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LoadBalancer.html
- containerName: "{{ deploy_container.container_name }}"
containerPort: "{{ deploy_container.aws_ecs.target_group_port }}"
targetGroupArn: "{{ _aws_ecs_target_group.target_group_arn }}"
network_configuration:
subnets: "{{ _aws_ecs_cluster_private_subnets_ids }}" # internal private subnet
security_groups: "{{ deploy_container.aws_ecs.security_groups }}"
assign_public_ip: "{{ deploy_container.aws_ecs.service_public_container_ip }}"
tags: "{{ deploy_container.aws_ecs.tags }}"
enable_execute_command: "{{ deploy_container.aws_ecs.service_enable_ssm }}"
force_new_deployment: "{{ deploy_container.aws_ecs.service_force_refresh }}"
wait: true
delegate_to: localhost
- name: Create target tracking scaling policy for ECS service.
community.aws.application_autoscaling_policy:
region: "{{ deploy_container.aws_ecs.region }}"
profile: "{{ deploy_container.aws_ecs.aws_profile }}"
state: present
policy_name: "{{ deploy_container.aws_ecs.family_name }}"
service_namespace: ecs
resource_id: "service/{{ deploy_container.aws_ecs.cluster_name }}/{{ deploy_container.aws_ecs.family_name }}"
scalable_dimension: ecs:service:DesiredCount
minimum_tasks: "{{ deploy_container.aws_ecs.task_minimum_count }}"
maximum_tasks: "{{ deploy_container.aws_ecs.task_maximum_count }}"
policy_type: TargetTrackingScaling
target_tracking_scaling_policy_configuration:
PredefinedMetricSpecification:
PredefinedMetricType: "{{ deploy_container.aws_ecs.service_autoscale_metric_type }}"
ScaleInCooldown: "{{ deploy_container.aws_ecs.service_autoscale_in_cooldown }}"
ScaleOutCooldown: "{{ deploy_container.aws_ecs.service_autoscale_out_cooldown }}"
DisableScaleIn: false
TargetValue: "{{ deploy_container.aws_ecs.service_autoscale_target_value }}"
delegate_to: localhost
- name: Initialise the domains loop var with main domain entry DNS settings.
ansible.builtin.set_fact:
_aws_ecs_cluster_dns_all_domains:
- domain: "{{ deploy_container.aws_ecs.domain_name }}"
zone: "{{ deploy_container.aws_ecs.route_53.zone }}"
aws_profile: "{{ deploy_container.aws_ecs.route_53.aws_profile }}"
- name: Add extra_domains so we can loop through DNS records.
ansible.builtin.set_fact:
_aws_ecs_cluster_dns_all_domains: "{{ _aws_ecs_cluster_dns_all_domains + [{'domain': item.domain, 'zone': item.zone, 'aws_profile': item.aws_profile}] }}"
loop: "{{ deploy_container.aws_ecs.acm.extra_domains }}"
when:
- deploy_container.aws_ecs.acm.extra_domains | length > 0
- name: Add DNS records in Route 53.
amazon.aws.route53:
state: present
profile: "{{ item.aws_profile }}"
zone: "{{ item.zone }}"
record: "{{ item.domain }}"
type: CNAME
value: "{{ _aws_ecs_cluster_alb.dns_name }}"
overwrite: true
loop: "{{ _aws_ecs_cluster_dns_all_domains }}"
when:
- deploy_container.aws_ecs.route_53.zone | length > 0