#!/bin/bash -eux # (c) 2016, John Barker <jobarker@redhat.com> # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see <http://www.gnu.org/licenses/>. ######################################################## # FIXME Describe purpose, process, directory structure, and state/variables readonly PROG="${0##*/}" readonly LOCKFILE_DIR=/tmp readonly LOCK_FD=200 ## # Validate command line arguments if [ "$#" -ne 2 ]; then echo "Invalid arguments provided" >&2 echo >&2 echo "USAGE: $0 platform branch" >&2 echo >&2 echo " $0 ios devel" >&2 echo " $0 junos stable-2.2" >&2 exit 2 fi platform=$1 branches=$2 inventory="inventory.network" # FIXME This file will updating to reference the DUT VMs once they exist # FIXME Describe directory structure here basedir="/tmp/run-network-test" log_root="/var/www/html/network-tests/logs" #DEBUG_LOGFILE="${basedir}/${PROG}-$(date '+%s').log" main() { validate_tools setup_environment echo "Platform: '${platform}'" echo "Branches: '${branches}'" # Ensure we don't run more than one instance of the tests per platform. # As we only have one test machine per platform we can't run more than one test # at once # Use the flock method from http://www.kfirlavi.com/blog/2012/11/06/elegant-locking-of-bash-program/ lock "${PROG}-${platform}" \ || eexit "Only one instance of ${PROG} can run on ${platform} at one time." run_tests } setup_environment() { if [ -d "${basedir}" ]; then mkdir -p "${basedir}" fi # FIXME Create HTML template if it doesn't already exist if [ ! -e "${log_root}/results.html" ]; then # First run so write out the top of the HTML results page echo "One time setup: Creating '${log_root}/results.html'" cat << 'EOF' > "${log_root}/results.html" <html> <title>Ansible Network Test Results</title> <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/jq-2.2.3/dt-1.10.12/datatables.min.css"/> <script type="text/javascript" src="https://cdn.datatables.net/v/dt/jq-2.2.3/dt-1.10.12/datatables.min.js"></script> <script> // https://datatables.net/blog/2014-12-18 May need this $(document).ready(function(){ $('#results').DataTable({ // Newest result on top "order": [[ 0, "desc" ]], // show all results paging: false }); }); </script> <body> <table id="results" class="datatable table table-striped table-bordered display" cellspacing="0" width="100%"> <thead> <tr> <th>Date</th> <th>Branch</th> <th>sha1</th> <th>Platform</th> <th>Result</th> </tr> </thead> <tbody> EOF fi } # We key of platform as the Test VMs are the limiting factor, not the branches # run-network-test/platform/devel run_tests() { for branch in ${branches//,/ } do echo "Inspecting: ${branch}" echo "Updating git repo..." branch_dir="${basedir}/${platform}/${branch}" ansible_dir="${branch_dir}/ansible" if [ -d "${ansible_dir}" ]; then git -C "${ansible_dir}" pull else git clone "https://github.com/ansible/ansible.git" "${ansible_dir}" fi # FIXME Revert any files left over from a previous run # Ensure we have the correct branch and submodules checked out git -C "${ansible_dir}" checkout "${branch}" git -C "${ansible_dir}" submodule update --init ## # Have we already ran tests on this commit checkout_sha="$(git -C "${ansible_dir}" rev-parse HEAD )" echo "${checkout_sha}" # Check against existing sha if [ -e "${branch_dir}/last-tested.sha" ]; then if [ "x${checkout_sha}" = "x$(cat "${branch_dir}/last-tested.sha")" ]; then echo "SKIPPING: $branch '${checkout_sha}' Has already been tested" continue # to the next branch fi fi echo "INFO $branch which sha1 of ${checkout_sha} has not been tested yet" echo "${checkout_sha}" > "${branch_dir}/last-tested.sha" logdir_for_this_run="${log_root}/${branch}/${platform}/${checkout_sha}" mkdir -p "${logdir_for_this_run}" echo "env-setup..." source "${ansible_dir}/hacking/env-setup" ansible_exit_value=0 cd "${ansible_dir}/test/integration" echo "Running Tests..." echo "Logs will be written to: ${log_root}/results.html" ansible-playbook --version > "${logdir_for_this_run}/ansible.log" 2>&1 ANSIBLE_FORCE_COLOR=1 ANSIBLE_ROLES_PATH=targets time -p ansible-playbook \ -vvv \ -i ${inventory} \ "${platform}.yaml" >> "${logdir_for_this_run}/ansible.log" 2>&1 || ansible_exit_value=$? echo "Ansible exited with: ${ansible_exit_value}" ### # Format logs # Generate HTML version ansi2html < "${logdir_for_this_run}/ansible.log" > "${logdir_for_this_run}/ansible.html" # Strip escape characters sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" "${logdir_for_this_run}/ansible.log" > "${logdir_for_this_run}/ansible.txt" # Write row to HTML table # This is horrible, though it gives us a basic table of results # It abuses the fact that we don't *have* to have "</tbody></table></body></html> # Assume tests are failing unless they pass. # In the future we could look up the exit value to detect the difference between # failing test and machine not reachable result_cell="<td bgcolor='red'>${ansible_exit_value}</td>" if [ "${ansible_exit_value}" -eq "0" ]; then result_cell="<td bgcolor='green'>${ansible_exit_value}</td>" fi gh_link="<a href='https://github.com/ansible/ansible/commits/${checkout_sha}'>${checkout_sha}</a>" echo "<tr><td><a href='${branch}/${platform}/${checkout_sha}/ansible.html'>$(date -R)</a></td><td>${branch}</td><td>${gh_link}</td><td>${platform}</td>${result_cell}</tr>" >> "${log_root}/results.html" if [ "${ansible_exit_value}" -ne "0" ]; then # Display the last few lines of the log tail -n 20 "${logdir_for_this_run}/ansible.log" fi echo "Logs written to: ${logdir_for_this_run}" done } validate_tools() { # FIXME echo "In validate_tools" if ! [ -x "$(command -v git)" ]; then eexit "'git' is not installed." >&2 fi if ! [ -x "$(command -v ansi2html)" ]; then eexit "'ansi2html' is not installed. Please install with 'sudo pip install ansi2html'" >&2 fi } upload_to_s3() { # FIXME echo "In upload_to_s3" } lock() { local prefix=$1 local fd=${2:-$LOCK_FD} local lock_file=$LOCKFILE_DIR/$prefix.lock # create lock file eval "exec $fd>$lock_file" # acquire the lock flock -n "${fd}" \ && return 0 \ || return 1 } eexit() { echo "$1" exit 1 } # Log everything of interest to syslog and to disk # Based on https://nicolaw.uk/#BashScriptDebugSyslog exec > >(2>&-;logger -s -t "$PROG[$$]" -p user.info 2>&1) 2> >(logger -s -t "$PROG[$$]" -p user.error) ls ps >&2 main "$@"