blob: b0d735ca01891c4371e5a38cecaa608cc5861ded [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 Naser4badc922022-12-10 21:17:46 +000028 - name: Upload logs to object storage
29 ignore_errors: True
30 when:
Michiel Piscaer7d40bf22022-12-16 08:15:31 +010031 - lookup('env', 'GITHUB_RUN_ID')|length > 0
32 - lookup('env', 'GITHUB_RUN_NUMBER')|length > 0
Mohammed Naser4badc922022-12-10 21:17:46 +000033 vars:
34 build_id: "{{ lookup('env', 'GITHUB_RUN_ID') }}-{{ lookup('env', 'GITHUB_RUN_NUMBER') }}"
35 container_name: atmosphere-ci-logs
36 block:
Mohammed Naserae64a6f2023-01-05 15:36:57 +000037 - name: Describe all cluster-scoped objects
38 become: true
39 shell: |-
40 set -e
41 export OBJECT_TYPE=node,clusterrole,clusterrolebinding,storageclass,namespace
42 export PARALLELISM_FACTOR=4
43 function list_objects () {
44 printf ${OBJECT_TYPE} | xargs -d ',' -I {} -P1 -n1 bash -c 'echo "$@"' _ {}
45 }
46 export -f list_objects
47 function name_objects () {
48 export OBJECT=$1
49 kubectl get ${OBJECT} -o name | xargs -L1 -I {} -P1 -n1 bash -c 'echo "${OBJECT} ${1#*/}"' _ {}
50 }
51 export -f name_objects
52 function get_objects () {
53 input=($1)
54 export OBJECT=${input[0]}
55 export NAME=${input[1]#*/}
56 echo "${OBJECT}/${NAME}"
57 DIR="{{ logs_dir }}/objects/cluster/${OBJECT}"
58 mkdir -p ${DIR}
59 kubectl get ${OBJECT} ${NAME} -o yaml > "${DIR}/${NAME}.yaml"
60 kubectl describe ${OBJECT} ${NAME} > "${DIR}/${NAME}.txt"
61 }
62 export -f get_objects
63 list_objects | \
64 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'name_objects "$@"' _ {} | \
65 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_objects "$@"' _ {}
66 args:
67 executable: /bin/bash
68
69 - name: Describe all namespace-scoped objects
70 become: true
71 shell: |-
72 set -e
73 export OBJECT_TYPE=configmaps,cronjobs,daemonsets,deployment,endpoints,ingresses,jobs,networkpolicies,pods,podsecuritypolicies,persistentvolumeclaims,rolebindings,roles,secrets,serviceaccounts,services,statefulsets
74 export PARALLELISM_FACTOR=4
75 function get_namespaces () {
76 kubectl get namespaces -o name | awk -F '/' '{ print $NF }'
77 }
78 function list_namespaced_objects () {
79 export NAMESPACE=$1
80 printf ${OBJECT_TYPE} | xargs -d ',' -I {} -P1 -n1 bash -c 'echo "${NAMESPACE} $@"' _ {}
81 }
82 export -f list_namespaced_objects
83 function name_objects () {
84 input=($1)
85 export NAMESPACE=${input[0]}
86 export OBJECT=${input[1]}
87 kubectl get -n ${NAMESPACE} ${OBJECT} -o name | xargs -L1 -I {} -P1 -n1 bash -c 'echo "${NAMESPACE} ${OBJECT} $@"' _ {}
88 }
89 export -f name_objects
90 function get_objects () {
91 input=($1)
92 export NAMESPACE=${input[0]}
93 export OBJECT=${input[1]}
94 export NAME=${input[2]#*/}
95 echo "${NAMESPACE}/${OBJECT}/${NAME}"
96 DIR="{{ logs_dir }}/objects/namespaced/${NAMESPACE}/${OBJECT}"
97 mkdir -p ${DIR}
98 kubectl get -n ${NAMESPACE} ${OBJECT} ${NAME} -o yaml > "${DIR}/${NAME}.yaml"
99 kubectl describe -n ${NAMESPACE} ${OBJECT} ${NAME} > "${DIR}/${NAME}.txt"
100 }
101 export -f get_objects
102 get_namespaces | \
103 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'list_namespaced_objects "$@"' _ {} | \
104 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'name_objects "$@"' _ {} | \
105 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_objects "$@"' _ {}
106 args:
107 executable: /bin/bash
108
109 - name: Retrieve all container logs, current and previous (if they exist)
110 become: true
111 shell: |-
112 set -e
113 PARALLELISM_FACTOR=4
114 function get_namespaces () {
115 kubectl get namespaces -o name | awk -F '/' '{ print $NF }'
116 }
117 function get_pods () {
118 NAMESPACE=$1
119 kubectl get pods -n ${NAMESPACE} -o name | awk -F '/' '{ print $NF }' | xargs -L1 -P 1 -I {} echo ${NAMESPACE} {}
120 }
121 export -f get_pods
122 function get_pod_logs () {
123 NAMESPACE=${1% *}
124 POD=${1#* }
125 INIT_CONTAINERS=$(kubectl get pod $POD -n ${NAMESPACE} -o jsonpath="{.spec.initContainers[*].name}")
126 CONTAINERS=$(kubectl get pod $POD -n ${NAMESPACE} -o jsonpath="{.spec.containers[*].name}")
127 for CONTAINER in ${INIT_CONTAINERS} ${CONTAINERS}; do
128 echo "${NAMESPACE}/${POD}/${CONTAINER}"
129 mkdir -p "{{ logs_dir }}/pod-logs/${NAMESPACE}/${POD}"
130 mkdir -p "{{ logs_dir }}/pod-logs/failed-pods/${NAMESPACE}/${POD}"
131 kubectl logs ${POD} -n ${NAMESPACE} -c ${CONTAINER} > "{{ logs_dir }}/pod-logs/${NAMESPACE}/${POD}/${CONTAINER}.txt"
132 kubectl logs --previous ${POD} -n ${NAMESPACE} -c ${CONTAINER} > "{{ logs_dir }}/pod-logs/failed-pods/${NAMESPACE}/${POD}/${CONTAINER}.txt"
133 done
134 find {{ logs_dir }} -type f -empty -print -delete
135 find {{ logs_dir }} -empty -type d -delete
136 }
137 export -f get_pod_logs
138 get_namespaces | \
139 xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_pods "$@"' _ {} | \
140 xargs -r -n 2 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_pod_logs "$@"' _ {}
141 args:
142 executable: /bin/bash
143
Mohammed Naser4badc922022-12-10 21:17:46 +0000144 - name: Authenticate to cloud to get token to use in Swift client
145 delegate_to: localhost
146 openstack.cloud.auth:
147 register: _auth
148
149 - name: Generate storage URL
150 set_fact:
151 storage_url: "{{ ((service_catalog | selectattr('name', 'equalto', 'swift') | first).endpoints | selectattr('interface', 'equalto', 'public') | first).url }}"
152
153 - name: Install Swift client
154 become: true
155 ansible.builtin.apt:
156 name: ['python3-swiftclient', 'tree']
157 state: present
158
159 - name: Generate listing for all files
160 become: true
161 shell: tree -H '.' --charset utf-8 -o {{ logs_dir }}/index.html {{ logs_dir }}
162
163 - name: Upload logs to swift
164 shell: |-
165 set -e
166 swift post -H "X-Container-Read: .r:*,.rlistings" {{ container_name }}
167 swift upload -H "X-Delete-After: 604800" -m 'web-index:index.html' --object-name {{ build_id }} {{ container_name }} {{ logs_dir }}
168 environment:
169 OS_STORAGE_URL: "{{ storage_url }}"
170 OS_AUTH_TOKEN: "{{ auth_token }}"
171
172 - name: Print logs URL
173 debug:
174 msg: "Logs are available at {{ storage_url }}/{{ container_name }}/{{ build_id }}/index.html"
175
Mohammed Naser336caf42022-03-11 17:56:45 -0500176- hosts: localhost
177 connection: local
178 gather_facts: false
179 no_log: "{{ molecule_no_log }}"
180 vars:
Mohammed Naser46e15522022-03-19 16:07:44 -0400181 workspace_path: "{{ lookup('env', 'MOLECULE_SCENARIO_DIRECTORY') }}"
Michiel Piscaer97b7fd32022-03-17 12:15:21 +0100182
183 stack_name: "{{ lookup('env', 'ATMOSPHERE_STACK_NAME') | default('atmosphere', True) }}"
Mohammed Naser336caf42022-03-11 17:56:45 -0500184 tasks:
185 - os_stack:
186 name: "{{ stack_name }}"
187 state: absent
188
189 - file:
190 path: "{{ molecule_instance_config }}"
191 state: absent
Mohammed Naser206e5f82022-03-16 20:21:14 -0400192
okozachenko674f9b72022-04-19 01:28:33 +1000193 - name: Capture var files to delete
194 find:
195 paths:
196 - "{{ workspace_path }}/group_vars"
197 - "{{ workspace_path }}/host_vars"
198 file_type: file
199 recurse: true
200 excludes:
201 - "molecule.yml"
202 register: _var_files
203
204 - name: Delete var files
205 file:
206 path: "{{ item.path }}"
207 state: absent
208 with_items: "{{ _var_files['files'] }}"