blob: b0d735ca01891c4371e5a38cecaa608cc5861ded [file] [log] [blame] [edit]
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# NOTE(mnaser): We're using this playbook to capture logs for the run since
# there is no Molecule phase that runs after the converge phase.
- hosts: controllers[0]
gather_facts: false
ignore_unreachable: true
vars:
logs_dir: /tmp/logs
tasks:
- name: End the play if the infrastructure is not deployed
ansible.builtin.meta: end_host
when:
- ansible_host is not defined
- name: Upload logs to object storage
ignore_errors: True
when:
- lookup('env', 'GITHUB_RUN_ID')|length > 0
- lookup('env', 'GITHUB_RUN_NUMBER')|length > 0
vars:
build_id: "{{ lookup('env', 'GITHUB_RUN_ID') }}-{{ lookup('env', 'GITHUB_RUN_NUMBER') }}"
container_name: atmosphere-ci-logs
block:
- name: Describe all cluster-scoped objects
become: true
shell: |-
set -e
export OBJECT_TYPE=node,clusterrole,clusterrolebinding,storageclass,namespace
export PARALLELISM_FACTOR=4
function list_objects () {
printf ${OBJECT_TYPE} | xargs -d ',' -I {} -P1 -n1 bash -c 'echo "$@"' _ {}
}
export -f list_objects
function name_objects () {
export OBJECT=$1
kubectl get ${OBJECT} -o name | xargs -L1 -I {} -P1 -n1 bash -c 'echo "${OBJECT} ${1#*/}"' _ {}
}
export -f name_objects
function get_objects () {
input=($1)
export OBJECT=${input[0]}
export NAME=${input[1]#*/}
echo "${OBJECT}/${NAME}"
DIR="{{ logs_dir }}/objects/cluster/${OBJECT}"
mkdir -p ${DIR}
kubectl get ${OBJECT} ${NAME} -o yaml > "${DIR}/${NAME}.yaml"
kubectl describe ${OBJECT} ${NAME} > "${DIR}/${NAME}.txt"
}
export -f get_objects
list_objects | \
xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'name_objects "$@"' _ {} | \
xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_objects "$@"' _ {}
args:
executable: /bin/bash
- name: Describe all namespace-scoped objects
become: true
shell: |-
set -e
export OBJECT_TYPE=configmaps,cronjobs,daemonsets,deployment,endpoints,ingresses,jobs,networkpolicies,pods,podsecuritypolicies,persistentvolumeclaims,rolebindings,roles,secrets,serviceaccounts,services,statefulsets
export PARALLELISM_FACTOR=4
function get_namespaces () {
kubectl get namespaces -o name | awk -F '/' '{ print $NF }'
}
function list_namespaced_objects () {
export NAMESPACE=$1
printf ${OBJECT_TYPE} | xargs -d ',' -I {} -P1 -n1 bash -c 'echo "${NAMESPACE} $@"' _ {}
}
export -f list_namespaced_objects
function name_objects () {
input=($1)
export NAMESPACE=${input[0]}
export OBJECT=${input[1]}
kubectl get -n ${NAMESPACE} ${OBJECT} -o name | xargs -L1 -I {} -P1 -n1 bash -c 'echo "${NAMESPACE} ${OBJECT} $@"' _ {}
}
export -f name_objects
function get_objects () {
input=($1)
export NAMESPACE=${input[0]}
export OBJECT=${input[1]}
export NAME=${input[2]#*/}
echo "${NAMESPACE}/${OBJECT}/${NAME}"
DIR="{{ logs_dir }}/objects/namespaced/${NAMESPACE}/${OBJECT}"
mkdir -p ${DIR}
kubectl get -n ${NAMESPACE} ${OBJECT} ${NAME} -o yaml > "${DIR}/${NAME}.yaml"
kubectl describe -n ${NAMESPACE} ${OBJECT} ${NAME} > "${DIR}/${NAME}.txt"
}
export -f get_objects
get_namespaces | \
xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'list_namespaced_objects "$@"' _ {} | \
xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'name_objects "$@"' _ {} | \
xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_objects "$@"' _ {}
args:
executable: /bin/bash
- name: Retrieve all container logs, current and previous (if they exist)
become: true
shell: |-
set -e
PARALLELISM_FACTOR=4
function get_namespaces () {
kubectl get namespaces -o name | awk -F '/' '{ print $NF }'
}
function get_pods () {
NAMESPACE=$1
kubectl get pods -n ${NAMESPACE} -o name | awk -F '/' '{ print $NF }' | xargs -L1 -P 1 -I {} echo ${NAMESPACE} {}
}
export -f get_pods
function get_pod_logs () {
NAMESPACE=${1% *}
POD=${1#* }
INIT_CONTAINERS=$(kubectl get pod $POD -n ${NAMESPACE} -o jsonpath="{.spec.initContainers[*].name}")
CONTAINERS=$(kubectl get pod $POD -n ${NAMESPACE} -o jsonpath="{.spec.containers[*].name}")
for CONTAINER in ${INIT_CONTAINERS} ${CONTAINERS}; do
echo "${NAMESPACE}/${POD}/${CONTAINER}"
mkdir -p "{{ logs_dir }}/pod-logs/${NAMESPACE}/${POD}"
mkdir -p "{{ logs_dir }}/pod-logs/failed-pods/${NAMESPACE}/${POD}"
kubectl logs ${POD} -n ${NAMESPACE} -c ${CONTAINER} > "{{ logs_dir }}/pod-logs/${NAMESPACE}/${POD}/${CONTAINER}.txt"
kubectl logs --previous ${POD} -n ${NAMESPACE} -c ${CONTAINER} > "{{ logs_dir }}/pod-logs/failed-pods/${NAMESPACE}/${POD}/${CONTAINER}.txt"
done
find {{ logs_dir }} -type f -empty -print -delete
find {{ logs_dir }} -empty -type d -delete
}
export -f get_pod_logs
get_namespaces | \
xargs -r -n 1 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_pods "$@"' _ {} | \
xargs -r -n 2 -P ${PARALLELISM_FACTOR} -I {} bash -c 'get_pod_logs "$@"' _ {}
args:
executable: /bin/bash
- name: Authenticate to cloud to get token to use in Swift client
delegate_to: localhost
openstack.cloud.auth:
register: _auth
- name: Generate storage URL
set_fact:
storage_url: "{{ ((service_catalog | selectattr('name', 'equalto', 'swift') | first).endpoints | selectattr('interface', 'equalto', 'public') | first).url }}"
- name: Install Swift client
become: true
ansible.builtin.apt:
name: ['python3-swiftclient', 'tree']
state: present
- name: Generate listing for all files
become: true
shell: tree -H '.' --charset utf-8 -o {{ logs_dir }}/index.html {{ logs_dir }}
- name: Upload logs to swift
shell: |-
set -e
swift post -H "X-Container-Read: .r:*,.rlistings" {{ container_name }}
swift upload -H "X-Delete-After: 604800" -m 'web-index:index.html' --object-name {{ build_id }} {{ container_name }} {{ logs_dir }}
environment:
OS_STORAGE_URL: "{{ storage_url }}"
OS_AUTH_TOKEN: "{{ auth_token }}"
- name: Print logs URL
debug:
msg: "Logs are available at {{ storage_url }}/{{ container_name }}/{{ build_id }}/index.html"
- hosts: localhost
connection: local
gather_facts: false
no_log: "{{ molecule_no_log }}"
vars:
workspace_path: "{{ lookup('env', 'MOLECULE_SCENARIO_DIRECTORY') }}"
stack_name: "{{ lookup('env', 'ATMOSPHERE_STACK_NAME') | default('atmosphere', True) }}"
tasks:
- os_stack:
name: "{{ stack_name }}"
state: absent
- file:
path: "{{ molecule_instance_config }}"
state: absent
- name: Capture var files to delete
find:
paths:
- "{{ workspace_path }}/group_vars"
- "{{ workspace_path }}/host_vars"
file_type: file
recurse: true
excludes:
- "molecule.yml"
register: _var_files
- name: Delete var files
file:
path: "{{ item.path }}"
state: absent
with_items: "{{ _var_files['files'] }}"