Razique Mahroua
2020-03-18 b85c91a8192593f6b62f93e11c971868964343a9
commit | author | age
1874b6 1 ---
GC 2 - import_playbook: ../../setup_runtime.yml
3
4 - name: Backup event log of the user
5   hosts: localhost
6   connection: local
7   gather_facts: False
8   become: no
9   environment:
10     AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
11     AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
12     AWS_DEFAULT_REGION: "{{aws_region_final|d(aws_region)}}"
13   tasks:
564e9d 14     - name: Create Infra Key
GC 15       include_role:
16         name: infra-ec2-ssh-key
17       when: install_infra_ssh_key | default(false) | bool
18
1874b6 19     - name: Get fact for stack
GC 20       cloudformation_facts:
21         stack_name: "{{ project_tag }}"
22       register: stack_facts
23
24     - when: project_tag in stack_facts.ansible_facts.cloudformation
25       block:
26         - name: Grab and set stack creation_time
27           set_fact:
28             stack_creation_time: >-
29               {{ stack_facts.ansible_facts.cloudformation[project_tag].stack_description.creation_time }}
30             stack_status: >-
31               {{ stack_facts.ansible_facts.cloudformation[project_tag].stack_description.stack_status }}
32
33         - when: stack_status == "CREATE_COMPLETE"
34           block:
35             - name: Grab student user
36               set_fact:
37                 student_stack_user: >-
38                   {{ stack_facts.ansible_facts.cloudformation[project_tag].stack_outputs.StudentUser }}
39
40             - name: Backup event log for user
41               shell: >-
42                 aws cloudtrail lookup-events
43                 --lookup-attributes AttributeKey=Username,AttributeValue={{ student_stack_user }}
44                 --start-time {{ stack_creation_time }}
45                 --max-items 10000
46                 > {{ output_dir }}/{{ env_type }}_{{ guid }}_cloudtrail_event_log.json
47               when:
48                 - email is defined or owner is defined
49                 - run_cloudtrail | default(true) | bool
50               failed_when: false
51
52 - name: Build inventory
53   hosts: localhost
54   connection: local
55   gather_facts: False
56   become: no
57   tasks:
58     - when: cloud_provider == 'ec2'
59       block:
60       - name: Run infra-ec2-create-inventory Role
61         include_role:
62           name: infra-ec2-create-inventory
63
64       - name: Run Common SSH Config Generator Role
65         include_role:
66           name: infra-common-ssh-config-generate
67         when: "'bastions' in groups"
68
69 - import_playbook: ../../setup_runtime.yml
70
71 - name: Start clientVM and cluster instances if they are stopped
72   hosts: localhost
73   connection: local
74   gather_facts: False
75   become: no
76   environment:
77     AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
78     AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
79     AWS_DEFAULT_REGION: "{{aws_region_final|d(aws_region)}}"
80   tasks:
81     - when:
82         - stack_status is defined
83         - stack_status == 'CREATE_COMPLETE'
84       block:
85         - set_fact:
86             clientvm_id: "{{ hostvars[groups.bastions[0]].instance_id }}"
87           when:
88             - "'bastions' in groups"
89             - groups.bastions | length > 0
90
91         - fail:
92             msg: "No clientVM present"
93           when: >-
94             'bastions' not in groups or groups.bastions | length == 0
95
96         - when:
97             - stack_status is defined
98             - stack_status == 'CREATE_COMPLETE'
99           block:
100             - name: Start clientVM instance
101               command: "aws ec2 start-instances --instance-ids '{{clientvm_id}}'"
102               register: _startclientvm
103               until: _startclientvm is succeeded
104               retries: 10
105               delay: "{{ 60|random(start=3, step=1) }}"
106
107             - name: Get cluster instance Ids
108               command: >-
109                 aws ec2 describe-instances
110                 --filters
111                 "Name=tag:clusterid,Values={{ cluster_name }}"
112                 "Name=instance-state-name,Values=pending,running,shutting-down,stopping,stopped"
113                 --query 'Reservations[*].Instances[*].InstanceId'
114                 --output text
115               changed_when: false
116               # Sometimes deployment fails before any OCP instances is created, so comment this line:
117               # failed_when: instanceids.stdout | trim | length == 0
118               register: instanceids
119               until: instanceids is succeeded
120               retries: 10
121               delay: "{{ 60|random(start=3, step=1) }}"
122
123             - name: Start cluster instances
124               when: instanceids.stdout | trim | length > 0
125               command: >-
126                     aws ec2 start-instances --instance-ids {{ instanceids.stdout | trim }}
127               register: _startinstances
128               until: _startinstances is succeeded
129               retries: 10
130               delay: "{{ 60|random(start=3, step=1) }}"
131
132             - name: Wait for clientVM instance
133               command: "aws ec2 wait instance-running --instance-ids '{{clientvm_id}}'"
134
135             - name: Wait for cluster instances
136               when: instanceids.stdout | trim | length > 0
137               ignore_errors: true
138               command: >-
139                     aws ec2 wait instance-running
140                     --filters "Name=tag:clusterid,Values={{ cluster_name }}"
141
bf4161 142 - name: Remove workloads
JR 143   hosts: bastions
144   gather_facts: false
145   run_once: true
146   become: false
147   tasks:
b85c91 148   - name: Set Ansible Python interpreter to k8s virtualenv
RM 149     set_fact:
150       ansible_python_interpreter: /opt/virtualenvs/k8s/bin/python
bf4161 151   - name: Remove ocp workloads
JR 152     when:
153     - remove_workloads | d("") | length > 0
154     tags:
155     - remove_workloads
156     block:
157       - name: Set facts for remote access
158         set_fact:
159           ansible_ssh_extra_args: >-
160             {{ ansible_ssh_extra_args|d() }}
161             -F {{hostvars.localhost.output_dir}}/{{ env_type }}_{{ guid }}_ssh_conf
162       - name: Invoke roles to remove ocp workloads
163         include_role:
164           name: "{{ workload_loop_var }}"
165         vars:
166           ocp_username: "system:admin"
167           ACTION: "remove"
168         loop: "{{ remove_workloads }}"
169         loop_control:
170           loop_var: workload_loop_var
171
1874b6 172 - name: Destroy OCP 4 resources using the installer
GC 173   hosts: bastions
174   gather_facts: false
175   become: no
176   run_once: yes
177   tasks:
178     - when:
179         - hostvars.localhost.stack_status is defined
180         - hostvars.localhost.stack_status == 'CREATE_COMPLETE'
181       block:
182         - name: Set facts for remote access
183           set_fact:
184             ansible_ssh_extra_args: >-
185               {{ ansible_ssh_extra_args|d() }}
186               -F {{hostvars.localhost.output_dir}}/{{ env_type }}_{{ guid }}_ssh_conf
187
188         - name: Wait for linux host to be available
189           wait_for_connection:
190             timeout: 20
191
192         - name: Pack an archive of everything in case something goes wrong
193           become: yes
194           archive:
195             path:
196               - /home
197               - /root
198             dest: /tmp/home.tar.gz
9b7a76 199           # TODO: remove ignore_errors when https://github.com/ansible/ansible/issues/42090 is fixed
GC 200           ignore_errors: yes
1874b6 201
GC 202         - name: Fetch the archive
203           fetch:
204             flat: yes
205             src: /tmp/home.tar.gz
206             dest: "{{ hostvars.localhost.output_dir }}/{{ env_type }}_{{ guid }}_user_home.tar.gz"
207
208         - stat:
209             path: /home/{{ ansible_user }}/{{ cluster_name }}/metadata.json
210           register: statclusterdir
211
212         - name: Wait until the file /tmp/deployinprogress lockfile is absent
213           wait_for:
214             path: /tmp/deployinprogress
215             state: absent
216             timeout: 1800
217             sleep: 10
218
219         - when: statclusterdir.stat.exists
220           block:
3e92aa 221             - name: destroy terraform resources (openshift-install destroy cluster)
GC 222               command: openshift-install destroy cluster --dir=/home/{{ ansible_user }}/{{ cluster_name }}/
223               register: destroyr
224               async: 2400
225               poll: 30
226               retries: 3
227               delay: 10
228               until: destroyr is succeeded
1874b6 229
3e92aa 230             - set_fact:
GC 231                 oktodelete: yes
1874b6 232
3e92aa 233           always:
GC 234             - name: pack an archive of everything
235               archive:
236                 path: /home/{{ansible_user}}/{{ cluster_name }}
237                 dest: /tmp/{{ cluster_name }}.tar.gz
1874b6 238
3e92aa 239             - name: get archive of environment target dir
GC 240               fetch:
241                 flat: yes
242                 src: /tmp/{{ cluster_name }}.tar.gz
243                 dest: "{{ hostvars.localhost.output_dir }}/{{ env_type }}_{{ guid }}_{{ cluster_name }}.tar.gz"
1874b6 244         - when: not statclusterdir.stat.exists
GC 245           block:
246             - name: Detect cluster dir using the terraform file (/root)
247               find:
248                 file_type: file
249                 paths: /root
250                 pattern: terraform.tfstate
251                 recurse: yes
252                 depth: 5
253               become: yes
254               register: findr
255
256             - name: Destroy all clusters
257               loop: "{{ findr.files }}"
258               include_tasks: destroy_cluster.yml
259               vars:
260                 cluster_dir: "{{ item.path | dirname }}"
261                 username: root
262
263             - name: Detect cluster dir using the terraform file (/home)
264               find:
265                 file_type: file
266                 paths: /home
267                 pattern: terraform.tfstate
268                 recurse: yes
269                 depth: 5
270               become: yes
271               register: findr
272
273             - name: Destroy all clusters
274               loop: "{{ findr.files }}"
275               include_tasks: destroy_cluster.yml
276               vars:
277                 cluster_dir: "{{ item.path | dirname }}"
278                 username: "{{ item.path | dirname | regex_replace('/home/([^/]+).*', '\\1') }}"
279
280             - set_fact:
281                 oktodelete: yes
282       always:
283         - name: Test if janitor is present
284           shell: command -v janitor
285           register: commandjanitor
286           delegate_to: localhost
287           failed_when: false
288           changed_when: false
289
290         - when:
291             - commandjanitor.rc == 0
b43292 292             - run_janitor | default(false) | bool
1874b6 293           block:
GC 294             - name: Run janitor to get existing resources
295               environment:
296                 AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
297                 AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
298                 AWS_REGION: "{{aws_region_final|d(aws_region)}}"
299               command: >-
300                 janitor
301                 -u={{ hostvars.localhost.student_stack_user }}
302                 -t='{{ hostvars.localhost.stack_creation_time }}'
303                 -r
304                 -quiet
305               register: janitorreg
306               delegate_to: localhost
307
308             - debug:
309                 var: janitorreg.stdout
310
311             - name: Send email about remaining resources
312               when:
313                 - janitorreg.stdout_lines | length > 0
314                 - report_email is defined
315               mail:
316                 subject: "OCP4 lab: Remaining resources found for user {{ hostvars.localhost.student_stack_user }}"
317                 to: "{{ report_email }}"
318                 subtype: html
319                 body: |-
320                   <pre>
321                   {{ janitorreg.stdout }}
322                   </pre>
323                 from: "{{ report_from_email | d(report_email) }}"
324                 headers:
325                   - Reply-To={{ report_reply_to_email | d(report_email) }}
326               delegate_to: localhost
327
328             - name: Output janitor logs
329               when: report_email is not defined
330               debug:
331                 var: janitorreg.stdout
332
333 - name: Delete ocp4 provisioner stack
334   hosts: localhost
335   connection: local
336   gather_facts: False
337   become: no
338   environment:
339     AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
340     AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
341     AWS_DEFAULT_REGION: "{{aws_region_final|d(aws_region)}}"
342   tasks:
343     - set_fact:
344         aws_public_zone: "{{ guid }}.{{ subdomain_base_suffix | regex_replace('^\\.', '') }}."
345
346     - name: Grab zone ID
347       # use CLI here because the route53_zone module is not graceful and asks for all zones
348       # then iterates in python to find the one. This causes Throttling errors.
349       # https://github.com/ansible/ansible/blob/05c6ff79f9860dbd6b43cb4914ee749baf65b9f7/lib/ansible/modules/cloud/amazon/route53_zone.py#L145
350       command: >-
351         aws route53 list-hosted-zones-by-name
352         --dns-name {{ aws_public_zone }}
353         --max-items 4
b85c91 354         --output json
1874b6 355       register: awsroute53zone
GC 356       changed_when: false
b8bf96 357       retries: 5
b85c91 358       delay: "{{ 60|random(start=10, step=1) }}"
b8bf96 359       until: awsroute53zone is succeeded
1874b6 360
GC 361     - name: delete zones
362       include_tasks: delete_zone.yml
363       vars:
364         _zone: "{{ loopzone }}"
365         _hostedzoneid: "{{ loopzone.Id | regex_replace('/hostedzone/', '') }}"
366       when:
367         - loopzone.Name == aws_public_zone
368       loop: "{{ awsroute53zone.stdout|from_json|json_query('HostedZones') }}"
369       loop_control:
370         loop_var: loopzone
371
372     - name: Run infra-ec2-template-destroy
373       include_role:
374         name: infra-ec2-template-destroy
375       when:
376         # Before deleting the provisioner, make sure destroy terraform successfully run.
377         - stack_status is defined
378         - stack_status == 'CREATE_COMPLETE'
379         - "'bastions' in groups"
380         - groups.bastions | length > 0
381         - hostvars[groups.bastions[0]].oktodelete
382
383     - name: Run infra-ec2-template-destroy
384       include_role:
385         name: infra-ec2-template-destroy
386       when:
387         # delete stack if stack creation failed
388         - stack_status is defined
389         - stack_status != 'CREATE_COMPLETE'