blob: b1c3516dd71e3d015ddfe6d435aa1a520b03aad5 [file] [log] [blame]
Mohammed Naser336caf42022-03-11 17:56:45 -05001# Copyright (c) 2022 VEXXHOST, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
Mohammed Naser4badc922022-12-10 21:17:46 +000015# NOTE(mnaser): We're using this playbook to capture logs for the run since
16# there is no Molecule phase that runs after the converge phase.
17- hosts: controllers[0]
18 gather_facts: false
okozachenko120376e81f82022-12-25 02:11:20 +110019 ignore_unreachable: true
Mohammed Naser4badc922022-12-10 21:17:46 +000020 vars:
21 logs_dir: /tmp/logs
22 tasks:
23 - name: End the play if the infrastructure is not deployed
24 ansible.builtin.meta: end_host
25 when:
26 - ansible_host is not defined
27
Mohammed Naser9766b482023-01-03 00:51:05 -050028 - name: Describe all cluster-scoped objects
29 become: true
30 shell: |-
31 set -e
32 export OBJECT_TYPE=node,clusterrole,clusterrolebinding,storageclass,namespace
33 export PARALLELISM_FACTOR=4
34 function list_objects () {
35 printf ${OBJECT_TYPE} | xargs -d ',' -I {} -P1 -n1 bash -c 'echo "$@"' _ {}
36 }
37 export -f list_objects
38 function name_objects () {
39 export OBJECT=$1
40 kubectl get ${OBJECT} -o name | xargs -L1 -I {} -P1 -n1 bash -c 'echo "${OBJECT} ${1#*/}"' _ {}
41 }
42 export -f name_objects
43 function get_objects () {
44 input=($1)
45 export OBJECT=${input[0]}
46 export NAME=${input[1]#*/}
47 echo "${OBJECT}/${NAME}"
48 DIR="{{ logs_dir }}/objects/cluster/${OBJECT}"
49 mkdir -p ${DIR}
50 kubectl get ${OBJECT} ${NAME} -o yaml > "${DIR}/${NAME}.yaml"
51 kubectl describe ${OBJECT} ${NAME} > "${DIR}/${NAME}.txt"
52 }
53 export -f get_objects
54 list_objects | \
55 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'name_objects "$@"' _ {} | \
56 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_objects "$@"' _ {}
57 args:
58 executable: /bin/bash
59 ignore_errors: True
60
61 - name: Describe all namespace-scoped objects
62 become: true
63 shell: |-
64 set -e
65 export OBJECT_TYPE=configmaps,cronjobs,daemonsets,deployment,endpoints,ingresses,jobs,networkpolicies,pods,podsecuritypolicies,persistentvolumeclaims,rolebindings,roles,secrets,serviceaccounts,services,statefulsets
66 export PARALLELISM_FACTOR=4
67 function get_namespaces () {
68 kubectl get namespaces -o name | awk -F '/' '{ print $NF }'
69 }
70 function list_namespaced_objects () {
71 export NAMESPACE=$1
72 printf ${OBJECT_TYPE} | xargs -d ',' -I {} -P1 -n1 bash -c 'echo "${NAMESPACE} $@"' _ {}
73 }
74 export -f list_namespaced_objects
75 function name_objects () {
76 input=($1)
77 export NAMESPACE=${input[0]}
78 export OBJECT=${input[1]}
79 kubectl get -n ${NAMESPACE} ${OBJECT} -o name | xargs -L1 -I {} -P1 -n1 bash -c 'echo "${NAMESPACE} ${OBJECT} $@"' _ {}
80 }
81 export -f name_objects
82 function get_objects () {
83 input=($1)
84 export NAMESPACE=${input[0]}
85 export OBJECT=${input[1]}
86 export NAME=${input[2]#*/}
87 echo "${NAMESPACE}/${OBJECT}/${NAME}"
88 DIR="{{ logs_dir }}/objects/namespaced/${NAMESPACE}/${OBJECT}"
89 mkdir -p ${DIR}
90 kubectl get -n ${NAMESPACE} ${OBJECT} ${NAME} -o yaml > "${DIR}/${NAME}.yaml"
91 kubectl describe -n ${NAMESPACE} ${OBJECT} ${NAME} > "${DIR}/${NAME}.txt"
92 }
93 export -f get_objects
94 get_namespaces | \
95 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'list_namespaced_objects "$@"' _ {} | \
96 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'name_objects "$@"' _ {} | \
97 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_objects "$@"' _ {}
98 args:
99 executable: /bin/bash
100 ignore_errors: True
101
Mohammed Naser4badc922022-12-10 21:17:46 +0000102 - name: Retrieve all container logs, current and previous (if they exist)
103 become: true
104 shell: |-
105 set -e
106 PARALLELISM_FACTOR=4
107 function get_namespaces () {
108 kubectl get namespaces -o name | awk -F '/' '{ print $NF }'
109 }
110 function get_pods () {
111 NAMESPACE=$1
112 kubectl get pods -n ${NAMESPACE} -o name | awk -F '/' '{ print $NF }' | xargs -L1 -P 1 -I {} echo ${NAMESPACE} {}
113 }
114 export -f get_pods
115 function get_pod_logs () {
116 NAMESPACE=${1% *}
117 POD=${1#* }
118 INIT_CONTAINERS=$(kubectl get pod $POD -n ${NAMESPACE} -o jsonpath="{.spec.initContainers[*].name}")
119 CONTAINERS=$(kubectl get pod $POD -n ${NAMESPACE} -o jsonpath="{.spec.containers[*].name}")
120 for CONTAINER in ${INIT_CONTAINERS} ${CONTAINERS}; do
121 echo "${NAMESPACE}/${POD}/${CONTAINER}"
122 mkdir -p "{{ logs_dir }}/pod-logs/${NAMESPACE}/${POD}"
123 mkdir -p "{{ logs_dir }}/pod-logs/failed-pods/${NAMESPACE}/${POD}"
124 kubectl logs ${POD} -n ${NAMESPACE} -c ${CONTAINER} > "{{ logs_dir }}/pod-logs/${NAMESPACE}/${POD}/${CONTAINER}.txt"
125 kubectl logs --previous ${POD} -n ${NAMESPACE} -c ${CONTAINER} > "{{ logs_dir }}/pod-logs/failed-pods/${NAMESPACE}/${POD}/${CONTAINER}.txt"
126 done
127 find {{ logs_dir }} -type f -empty -print -delete
128 find {{ logs_dir }} -empty -type d -delete
129 }
130 export -f get_pod_logs
131 get_namespaces | \
132 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_pods "$@"' _ {} | \
133 xargs -r -n 2 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_pod_logs "$@"' _ {}
134 args:
135 executable: /bin/bash
136 ignore_errors: True
137
138 - name: Upload logs to object storage
139 ignore_errors: True
140 when:
Michiel Piscaer7d40bf22022-12-16 08:15:31 +0100141 - lookup('env', 'GITHUB_RUN_ID')|length > 0
142 - lookup('env', 'GITHUB_RUN_NUMBER')|length > 0
Mohammed Naser4badc922022-12-10 21:17:46 +0000143 vars:
144 build_id: "{{ lookup('env', 'GITHUB_RUN_ID') }}-{{ lookup('env', 'GITHUB_RUN_NUMBER') }}"
145 container_name: atmosphere-ci-logs
146 block:
147 - name: Authenticate to cloud to get token to use in Swift client
148 delegate_to: localhost
149 openstack.cloud.auth:
150 register: _auth
151
152 - name: Generate storage URL
153 set_fact:
154 storage_url: "{{ ((service_catalog | selectattr('name', 'equalto', 'swift') | first).endpoints | selectattr('interface', 'equalto', 'public') | first).url }}"
155
156 - name: Install Swift client
157 become: true
158 ansible.builtin.apt:
159 name: ['python3-swiftclient', 'tree']
160 state: present
161
162 - name: Generate listing for all files
163 become: true
164 shell: tree -H '.' --charset utf-8 -o {{ logs_dir }}/index.html {{ logs_dir }}
165
166 - name: Upload logs to swift
167 shell: |-
168 set -e
169 swift post -H "X-Container-Read: .r:*,.rlistings" {{ container_name }}
170 swift upload -H "X-Delete-After: 604800" -m 'web-index:index.html' --object-name {{ build_id }} {{ container_name }} {{ logs_dir }}
171 environment:
172 OS_STORAGE_URL: "{{ storage_url }}"
173 OS_AUTH_TOKEN: "{{ auth_token }}"
174
175 - name: Print logs URL
176 debug:
177 msg: "Logs are available at {{ storage_url }}/{{ container_name }}/{{ build_id }}/index.html"
178
Mohammed Naser336caf42022-03-11 17:56:45 -0500179- hosts: localhost
180 connection: local
181 gather_facts: false
182 no_log: "{{ molecule_no_log }}"
183 vars:
Mohammed Naser46e15522022-03-19 16:07:44 -0400184 workspace_path: "{{ lookup('env', 'MOLECULE_SCENARIO_DIRECTORY') }}"
Michiel Piscaer97b7fd32022-03-17 12:15:21 +0100185
186 stack_name: "{{ lookup('env', 'ATMOSPHERE_STACK_NAME') | default('atmosphere', True) }}"
Mohammed Naser336caf42022-03-11 17:56:45 -0500187 tasks:
188 - os_stack:
189 name: "{{ stack_name }}"
190 state: absent
191
192 - file:
193 path: "{{ molecule_instance_config }}"
194 state: absent
Mohammed Naser206e5f82022-03-16 20:21:14 -0400195
okozachenko674f9b72022-04-19 01:28:33 +1000196 - name: Capture var files to delete
197 find:
198 paths:
199 - "{{ workspace_path }}/group_vars"
200 - "{{ workspace_path }}/host_vars"
201 file_type: file
202 recurse: true
203 excludes:
204 - "molecule.yml"
205 register: _var_files
206
207 - name: Delete var files
208 file:
209 path: "{{ item.path }}"
210 state: absent
211 with_items: "{{ _var_files['files'] }}"