#!/bin/sh
# PCP QA Test No. 1458
# Exercise access pmproxy with secure.enabled = false
#
# The main purpose of this is to test that the component works correctly
# when secure.enabled = false; we can expect the https URLs to fail.
#
# See https://github.com/performancecopilot/pcp/issues/1490

# Copyright (c) 2019,2021 Red Hat
# Modified by Netflix, Inc.
#

seq=`basename $0`
echo "QA output created by $seq"

# get standard environment, filters and checks
. ./common.product
. ./common.filter
. ./common.check

_check_valgrind
openssl help 2>/dev/null || _notrun "No openssl binary found"

if [ -f /etc/lsb-release ]
then
    . /etc/lsb-release
    if [ "$DISTRIB_ID" = Ubuntu ]
    then
	# This test fails for Ubuntu 19.10 with a myriad of errors involving
	# the use of uninitialized values.  The code paths very but typically
	# involve libuv -> libssl ->  libcrypto
	#
	case "$DISTRIB_RELEASE"
	in
	    19.10)
		_notrun "problems with libuv, libssl, libcrypto and valgrind on Ubuntu $DISTRIB_RELEASE"
		;;
	esac
    fi
fi

_cleanup()
{
    cd $here
    if $need_restore
    then
	need_restore=false
	_restore_config $PCP_SYSCONF_DIR/labels
	_sighup_pmcd
    fi
    $sudo rm -rf $tmp $tmp.*
}

status=1	# failure is the default!
need_restore=false
username=`id -u -n`
$sudo rm -rf $tmp $tmp.* $seq.full
trap "_cleanup; exit \$status" 0 1 2 3 15

_check_empty()
{
    tee -a $seq.full > $tmp.unfiltered
    if [ -s $tmp.unfiltered ]
    then
	echo "Botch: got output from curl"
    else
	echo "Good!, empty output from curl"
    fi
}

_filter_json()
{
    tee -a $seq.full > $tmp.unfiltered
    if [ -s $tmp.unfiltered ]
    then
	pmjson < $tmp.unfiltered > $tmp.filtered
	status=$?
	    if [ $status -eq 0 ]; then
	    cat $tmp.filtered | \
	    sed \
		-e '/"machineid": .*/d' \
		-e 's,"series": .*,"series": "SERIES",g' \
		-e 's,"context": .*,"context": "CONTEXT",g' \
		-e 's,"hostname": .*,"hostname": "HOSTNAME",g' \
		-e 's,"domainname": .*,"domainname": "DOMAINNAME",g' \
	    #end
	else
	    echo "Invalid JSON: $status"
	    cat $tmp.unfiltered
	    rm -f $tmp.context
	fi
    else
	echo "Botch: no output from curl"
    fi
}

_filter_port()
{
    sed \
        -e '/ ipv6 /d' \
	-e "s/ $port / PORT /g" \
    #end
}

# real QA test starts here
_save_config $PCP_SYSCONF_DIR/labels
need_restore=true

$sudo rm -rf $PCP_SYSCONF_DIR/labels/*
_sighup_pmcd

openssl req \
	-new -newkey rsa:4096 -days 365 -nodes -x509 \
	-subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.pcpqa.com" \
	-keyout $tmp.key -out $tmp.cert >$seq.full 2>&1
# creates a self-signed (insecure) certificate, so for testing only

echo "[redis]" >> $tmp.conf
echo "enabled = false" >> $tmp.conf
echo "[pmproxy]" >> $tmp.conf
echo "http.enabled = true" >> $tmp.conf
echo "secure.enabled = false" >> $tmp.conf

port=`_find_free_port`
mkdir -p $tmp.pmproxy/pmproxy
export PCP_RUN_DIR=$tmp.pmproxy
export PCP_TMP_DIR=$tmp.pmproxy

$_valgrind_clean_assert pmproxy -f -l- --timeseries \
	-c $tmp.conf -p $port -U $username \
	>$tmp.valout 2>$tmp.valerr &
pid=$!

echo "valgrind pid: $pid" >>$seq.full
echo "pmproxy port: $port" >>$seq.full

# valgrind takes awhile to fire up
i=0
while [ $i -lt 40 ]
do
    $PCP_BINADM_DIR/telnet-probe -c localhost $port && break
    sleep 1
    i=`expr $i + 1`
done
if $PCP_BINADM_DIR/telnet-probe -c localhost $port
then
    echo "Startup took $i secs" >>$seq.full
else
    echo "Arrgh: valgrind failed start pmproxy and get port $port ready after 30 secs"
    exit
fi

date >>$seq.full
echo "=== checking serial http operation ===" | tee -a $seq.full
for i in 1 2 3 4; do
    curl -Gs "http://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i
done
for i in 1 2 3 4; do
echo === out$i === | tee -a $seq.full
_filter_json < $tmp.out$i
done

date >>$seq.full
echo "=== checking parallel http operation ===" | tee -a $seq.full
for i in 1 2 3 4; do
    curl -Gs "http://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i & 2>/dev/null eval pid$i=$!
done
wait $pid1 $pid2 $pid3 $pid4
for i in 1 2 3 4; do
echo === out$i === | tee -a $seq.full
_filter_json < $tmp.out$i
done

date >>$seq.full
echo "=== checking serial https/TLS operation ===" | tee -a $seq.full
for i in 1 2 3 4; do
    curl -k -Gs "https://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i
done
for i in 1 2 3 4; do
echo === out$i === | tee -a $seq.full
_check_empty < $tmp.out$i
done

date >>$seq.full
echo "=== checking parallel https/TLS operation ===" | tee -a $seq.full
for i in 1 2 3 4; do
    curl -k -Gs "https://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i & 2>/dev/null eval pid$i=$!
done
wait $pid1 $pid2 $pid3 $pid4
for i in 1 2 3 4; do
echo === out$i === | tee -a $seq.full
_check_empty < $tmp.out$i
done

echo "=== check pmproxy is running ==="
pminfo -v -h localhost@localhost:$port hinv.ncpu
if [ $? -eq 0 ]; then
    echo "pmproxy check passed"
else
    echo "pmproxy check failed"
fi

# valgrind takes awhile to shutdown too
pmsignal $pid >/dev/null 2>&1
pmsleep 3.5
echo "=== valgrind stdout ===" | tee -a $seq.full
cat $tmp.valout | _filter_valgrind

echo "=== valgrind stderr ===" | tee -a $seq.full
cat $tmp.valerr | _filter_pmproxy_log | _filter_port

# final kill if it's spinning
$sudo kill -9 $pid >/dev/null 2>&1

# success, all done
status=0
exit
