1#!/usr/bin/env bash 2set -e 3 4if [ -d /var/cfengine ]; then 5 rm -rf /var/cfengine 6fi 7 8# Test assumes we start in core or masterfiles directory 9cd ../ 10 11if [ ! -d core ]; then 12 echo "Cloning core (master)" 13 git clone --recursive https://github.com/cfengine/core.git 14fi 15 16if [ ! -d masterfiles ]; then 17 echo "Cloning masterfiles (master)" 18 git clone --recursive https://github.com/cfengine/masterfiles.git 19fi 20 21echo "Checking for systemctl" 22systemctl --version 23 24cd core/ 25echo "Building CFEngine core" 26set +e 27git fetch --unshallow 2>&1 >> /dev/null 28git remote add upstream https://github.com/cfengine/core.git \ 29 && git fetch upstream 'refs/tags/*:refs/tags/*' 2>&1 >> /dev/null 30set -e 31 32./autogen.sh --enable-debug --with-systemd-service 33make 34 35echo "Installing CFEngine core" 36make install 37cd ../ 38 39cd masterfiles/ 40./autogen.sh 41echo "Installing CFEngine masterfiles" 42make install 43 44systemctl daemon-reload 45 46function print_ps { 47 set +e 48 echo "CFEngine processes:" 49 ps aux | grep [c]f- 50 51 echo "Valgrind processes:" 52 ps aux | grep [v]algrind 53 set -e 54} 55 56function no_errors { 57 set +e 58 grep -i "error" $1 59 grep -i "error" $1 && exit 1 60 set -e 61} 62 63function check_daemon_output { 64 echo "Examining $1:" 65 no_errors $1 66} 67 68function check_output { 69 set -e 70 if [ ! -f "$1" ]; then 71 echo "$1 does not exists!" 72 exit 1 73 fi 74 echo "Looking for problems in $1:" 75 grep -i "ERROR SUMMARY: 0 errors" "$1" 76 cat $1 | sed -e "/ 0 errors/d" -e "/and suppressed error/d" -e "/a memory error detector/d" -e "/This database contains unknown binary data/d" > filtered.txt 77 no_errors filtered.txt 78 set +e 79 grep -i "at 0x" filtered.txt 80 grep -i "at 0x" filtered.txt && exit 1 81 grep -i "by 0x" filtered.txt 82 grep -i "by 0x" filtered.txt && exit 1 83 grep -i "Failed to connect" filtered.txt 84 grep -i "Failed to connect" filtered.txt && exit 1 85 set -e 86} 87 88function check_serverd_valgrind_output { 89 if [ ! -f "$1" ]; then 90 echo "$1 does not exists!" 91 exit 1 92 fi 93 set -e 94 echo "Serverd has 1 expected valgrind error in travis because of old glibc" 95 echo "Because of this we use special assertions on output" 96 echo "Looking for problems in $1:" 97 grep -i "definitely lost" $1 98 grep -i "indirectly lost" $1 99 grep -i "ERROR SUMMARY" $1 100 grep -i "definitely lost: 0 bytes in 0 blocks" $1 101 grep -i "indirectly lost: 0 bytes in 0 blocks" $1 102 grep -i "ERROR SUMMARY: 0 errors" "$1" 103 104 cat $1 | sed -e "/ERROR SUMMARY/d" -e "/and suppressed error/d" -e "/a memory error detector/d" > filtered.txt 105 106 no_errors filtered.txt 107 set +e 108 grep -i "at 0x" filtered.txt 109 grep -i "at 0x" filtered.txt && exit 1 110 grep -i "by 0x" filtered.txt 111 grep -i "by 0x" filtered.txt && exit 1 112 set -e 113} 114 115function check_masterfiles_and_inputs { 116 set -e 117 echo "Comparing promises.cf from inputs and masterfiles:" 118 diff /var/cfengine/inputs/promises.cf /var/cfengine/masterfiles/promises.cf 119} 120 121/var/cfengine/bin/cf-agent --version 122 123VG_OPTS="--leak-check=full --track-origins=yes --error-exitcode=1" 124BOOTSTRAP_IP="$(ifconfig | grep -A1 Ethernet | sed '2!d;s/.*addr:\([0-9.]*\).*/\1/')" 125 126valgrind $VG_OPTS /var/cfengine/bin/cf-key 2>&1 | tee cf-key.txt 127check_output cf-key.txt 128valgrind $VG_OPTS /var/cfengine/bin/cf-agent -B $BOOTSTRAP_IP 2>&1 | tee bootstrap.txt 129check_output bootstrap.txt 130 131# Validate all databases here, because later, we cannot validate 132# cf_lastseen.lmdb: 133echo "Running cf-check diagnose --validate on all databases:" 134valgrind $VG_OPTS /var/cfengine/bin/cf-check diagnose --validate 2>&1 | tee cf_check_validate_all.txt 135check_output cf_check_validate_all.txt 136 137check_masterfiles_and_inputs 138 139print_ps 140 141echo "Stopping service to relaunch under valgrind" 142systemctl stop cfengine3 143sleep 10 144print_ps 145 146# The IP we bootstrapped to cannot actually be used for communication. 147# This ensures that cf-serverd binds to loopback interface, and cf-net 148# connects to it: 149echo "127.0.0.1" > /var/cfengine/policy_server.dat 150 151echo "Starting cf-serverd with valgrind in background:" 152valgrind $VG_OPTS --log-file=serverd.txt /var/cfengine/bin/cf-serverd --no-fork 2>&1 > serverd_output.txt & 153server_pid="$!" 154sleep 20 155 156echo "Starting cf-execd with valgrind in background:" 157valgrind $VG_OPTS --log-file=execd.txt /var/cfengine/bin/cf-execd --no-fork 2>&1 > execd_output.txt & 158exec_pid="$!" 159sleep 10 160 161print_ps 162 163echo "Running cf-net:" 164valgrind $VG_OPTS /var/cfengine/bin/cf-net GET /var/cfengine/masterfiles/promises.cf 2>&1 | tee get.txt 165check_output get.txt 166 167echo "Checking promises.cf diff (from cf-net GET):" 168diff ./promises.cf /var/cfengine/masterfiles/promises.cf 169 170echo "Running update.cf:" 171valgrind $VG_OPTS /var/cfengine/bin/cf-agent -K -f update.cf 2>&1 | tee update.txt 172check_output update.txt 173check_masterfiles_and_inputs 174echo "Running update.cf without local copy:" 175valgrind $VG_OPTS /var/cfengine/bin/cf-agent -K -f update.cf -D mpf_skip_local_copy_optimization 2>&1 | tee update2.txt 176check_output update2.txt 177check_masterfiles_and_inputs 178echo "Running promises.cf:" 179valgrind $VG_OPTS /var/cfengine/bin/cf-agent -K -f promises.cf 2>&1 | tee promises.txt 180check_output promises.txt 181 182# Dump all databases, use grep to filter the JSON lines 183# (optional whitespace then double quote or curly brackets). 184# Some of the databases have strings containing "error" 185# which check_output greps for. 186echo "Running cf-check dump:" 187valgrind $VG_OPTS /var/cfengine/bin/cf-check dump 2>&1 | grep -E '\s*[{}"]' --invert-match | tee cf_check_dump.txt 188check_output cf_check_dump.txt 189 190echo "Running cf-check diagnose on all databases" 191valgrind $VG_OPTS /var/cfengine/bin/cf-check diagnose 2>&1 | tee cf_check_diagnose.txt 192check_output cf_check_diagnose.txt 193 194# Because of the hack with bootstrap IP / policy_server.dat above 195# lastseen would not pass validation: 196echo "Running cf-check diagnose --validate on all databases except cf_lastseen.lmdb:" 197find /var/cfengine/state -name '*.lmdb' ! -name 'cf_lastseen.lmdb' -exec \ 198 valgrind $VG_OPTS /var/cfengine/bin/cf-check diagnose --validate {} + 2>&1 \ 199 | tee cf_check_validate_no_lastseen.txt 200check_output cf_check_validate_no_lastseen.txt 201 202echo "Checking that bootstrap ID doesn't change" 203/var/cfengine/bin/cf-agent --show-evaluated-vars | grep bootstrap_id > id_a 204/var/cfengine/bin/cf-agent -K --show-evaluated-vars | grep bootstrap_id > id_b 205cat id_a 206diff id_a id_b 207 208echo "Checking that bootstrap ID has expected length" 209[ `cat id_a | awk '{print $2}' | wc -c` -eq 41 ] 210 211print_ps 212 213echo "Checking that serverd and execd PIDs are still correct/alive:" 214ps -p $exec_pid 215ps -p $server_pid 216 217echo "Killing valgrind cf-execd" 218kill $exec_pid 219echo "Killing valgrind cf-serverd" 220kill $server_pid 221sleep 30 222 223echo "Output from cf-execd in valgrind:" 224cat execd.txt 225check_output execd.txt 226check_daemon_output execd_output.txt 227 228echo "Output from cf-serverd in valgrind:" 229cat serverd.txt 230check_serverd_valgrind_output serverd.txt 231check_daemon_output serverd_output.txt 232 233echo "Stopping cfengine3 service" 234systemctl stop cfengine3 235 236echo "Done killing" 237sleep 10 238print_ps 239 240echo "Check that bootstrap was successful" 241grep "This host assumes the role of policy server" bootstrap.txt 242grep "completed successfully!" bootstrap.txt 243 244echo "valgrind_health_check successful! (valgrind.sh)" 245