testing/integration/go.sh
#!/usr/bin/env bash
NS="kt-integration-test"
SHADOW_IMAGE="registry.cn-hangzhou.aliyuncs.com/rdc-incubator/kt-connect-shadow:vdev"
ROUTER_IMAGE="registry.cn-hangzhou.aliyuncs.com/rdc-incubator/kt-connect-router:vdev"
DOCKER_HOST=""
DNS_MODE="localDNS"
CONNECT_MODE="tun2socks"
EXCHANGE_MODE="scale"
MESH_MODE="auto"
declare -i RETRY_TIMES=10
CLEANUP_ONLY="N"
KEEP_PROOF="N"
# Print usage
function usage() {
echo "go.sh [--keep-proof] [--cleanup-only]"
}
# Log
function log() {
printf "\e[34m>>\e[0m ${*}\n"
}
# Exit with error
function fail() {
error "${@}"
if [ "${KEEP_PROOF}" != "Y" ]; then
cleanup
fi
exit 1
}
# Print error message
function error() {
log "\e[31m${*} !!!\e[0m"
log "check logs for detail: \e[33m$(ls -cr /tmp/kt-it-*.log)\e[0m"
}
# Test passed
function success() {
log "\e[32m${*} !!!\e[0m"
}
# Clean everything up
function cleanup() {
log "cleaning up ..."
sudo rm -rf ~root/.kt/pid/
rm -rf "${HOME}/.kt/pid/"
if [ "${DOCKER_HOST}" != "" ]; then
PID=$(ps aux | grep 'CfNgL 8080:localhost:8080' | grep -v 'grep' | awk '{print $2}')
if [ "${PID}" != "" ]; then
log "disconnect from docker host ${DOCKER_HOST}"
kill -15 ${PID}
fi
fi
docker rm -f tomcat
kubectl -n ${NS} delete deployment tomcat
kubectl -n ${NS} delete service tomcat
check_resources_cleaned
kubectl delete namespace ${NS}
}
# Wait all resource created by ktctl get cleaned
function check_resources_cleaned() {
for i in $(seq 10); do
sleep 6
log "checking resource clean up, ${i} times"
resource_count=$(kubectl -n ${NS} get pod,configmap,service | grep '^\(pod/\|configmap/\|service/\).*' | grep -v 'kube-root-ca\.crt' | wc -l)
if [ ${resource_count} -eq 0 ]; then
return
fi
done
kubectl -n ${NS} get pod,configmap,service -o wide >/tmp/kt-it-left.log
error "some resource are left in namespace ${NS}"
}
# Wait pod ready
function wait_for_pod() {
for i in $(seq 10); do
log "checking pod ${1}, ${i} times"
exist=$(kubectl -n ${NS} get pod | grep "^${1}-" | grep "${2}/${2}")
if [ "${exist}" != "" ]; then
return
fi
sleep 3
done
fail "failed to start pod ${1}"
}
# Check if background job running
function check_job() {
declare -i count=$(jobs | grep "${1}" | wc -l)
if [ ${count} -ne 1 ]; then fail "failed to setup ${1} job"; fi
}
# Check if ktctl pid file exists
function check_pid_file() {
if [ "${1}" = "connect" ]; then
kt_home=~root/.kt
with_sudo="sudo"
else
kt_home="${HOME}/.kt"
with_sudo=""
fi
pidFile=$(${with_sudo} ls -t "${kt_home}/pid/" | grep "${1}-.*\.pid" | head -1)
if [ "${pidFile}" = "" ]; then
fail "cannot find pid file for command ${1}"
fi
pid=$(cat "${pidFile}")
log "ktctl ${1} pid: ${pid}"
}
# Verify access specified url with result
function verify() {
target="${1}"
url="${2}"
if [ "${url:0:4}" != "http" ]; then
header="${2}"
url="${3}"
shift 3
else
shift 2
fi
log "accessing ${url}"
for c in $(seq ${RETRY_TIMES}); do
if [ "${header}" != "" ]; then
res=$(curl -H "${header}" --connect-timeout 2 -s ${url})
else
res=$(curl --connect-timeout 2 -s ${url})
fi
if [ "${res}" = "${*}" ]; then
return
fi
log "retry times: ${c}"
sleep 5
done
fail "failed to access ${target}, got: ${res}"
}
function prepare_cluster() {
# Require for root access
sudo true
if [ ${?} -ne 0 ]; then fail "failed to require root access"; fi
# Check environment is clean
existPid=$(ps aux | grep "ktctl" | grep -v "grep" | awk '{print $2}' | sort -n | head -1)
if [ "${existPid}" != "" ]; then fail "ktctl already running before test start (pid: ${existPid})"; fi
rm -f /tmp/kt-it-*.log
ktctl -n ${NS} clean >/tmp/kt-it-clean.log 2>&1
if [ ${?} -ne 0 ]; then fail "clean up failed (kubernetes cluster unreachable ?)"; fi
# Prepare test resources
kubectl create namespace ${NS}
kubectl -n ${NS} create deployment tomcat --image=tomcat:9 --port=8080
kubectl -n ${NS} expose deployment tomcat --port=8080 --target-port=8080
wait_for_pod tomcat 1
kubectl -n ${NS} exec deployment/tomcat -c tomcat -- /bin/bash \
-c 'mkdir -p webapps/ROOT; echo "kt-connect demo v1" > webapps/ROOT/index.html'
podIp=$(kubectl -n ${NS} get pod --selector app=tomcat -o jsonpath='{.items[0].status.podIP}')
log "tomcat pod-ip: ${podIp}"
if [ "${podIp}" = "" ]; then fail "failed to setup test deployment"; fi
clusterIP=$(kubectl -n ${NS} get service tomcat -o jsonpath='{.spec.clusterIP}')
log "tomcat cluster-ip: ${clusterIP}"
if [ "${clusterIP}" = "" ]; then fail "failed to setup test service"; fi
}
function test_ktctl_connect() {
# Test connect
if [ "${DOCKER_HOST}" == "" ]; then
sudo ktctl -d -n ${NS} -i ${SHADOW_IMAGE} -f connect --mode ${CONNECT_MODE} --dnsMode ${DNS_MODE} --dnsCacheTtl 10 >/tmp/kt-it-connect.log 2>&1 &
else
sudo ktctl -d -n ${NS} -i ${SHADOW_IMAGE} -f connect --mode ${CONNECT_MODE} --dnsMode ${DNS_MODE} --dnsCacheTtl 10 --excludeIps ${DOCKER_HOST#*@} >/tmp/kt-it-connect.log 2>&1 &
fi
wait_for_pod kt-connect 1
check_job connect
check_pid_file connect
verify "pod-ip" "http://${podIp}:8080" "kt-connect demo v1"
verify "cluster-ip" "http://${clusterIP}:8080" "kt-connect demo v1"
verify "service-domain-full-qualified" "http://tomcat.${NS}.svc.cluster.local:8080" "kt-connect demo v1"
verify "service-domain-with-namespace" "http://tomcat.${NS}:8080" "kt-connect demo v1"
verify "service-domain" "http://tomcat:8080" "kt-connect demo v1"
success "ktctl connect test passed"
}
function prepare_local() {
# Prepare local service
docker run -d --name tomcat -p 8080:8080 tomcat:9
if [ $? -eq 0 ]; then
log "local tomcat container started"
else
fail "failed to start local tomcat container"
fi
sleep 3
exist=$(docker ps -a | grep ' tomcat$' | grep -i ' Up ')
if [ "${exist}" = "" ]; then fail "failed to start up local tomcat container"; fi
docker exec tomcat /bin/bash -c 'mkdir -p webapps/ROOT; echo "kt-connect local v2" > webapps/ROOT/index.html'
if [ $? -ne 0 ]; then fail "failed to update tomcat index page content"; fi
if [ "${DOCKER_HOST}" != "" ]; then
ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -CfNgL 8080:localhost:8080 ${DOCKER_HOST}
fi
verify "local-service" "http://127.0.0.1:8080" "kt-connect local v2"
}
function test_ktctl_exchange() {
# Test exchange
ktctl -d -n ${NS} -i ${SHADOW_IMAGE} -f exchange deployment/tomcat --mode ${EXCHANGE_MODE} --expose 8080 >/tmp/kt-it-exchange.log 2>&1 &
wait_for_pod tomcat-kt-exchange 1
check_job exchange
check_pid_file exchange
verify "exchanged-service" "http://tomcat.${NS}.svc.cluster.local:8080" "kt-connect local v2"
success "ktctl exchange test passed"
}
function test_ktctl_mesh() {
# Test mesh
ktctl -d -n ${NS} -i ${SHADOW_IMAGE} -f mesh tomcat --mode ${MESH_MODE} --expose 8080 --versionMark ci \
--routerImage ${ROUTER_IMAGE} >/tmp/kt-it-mesh.log 2>&1 &
wait_for_pod tomcat-kt-mesh 1
check_job mesh
check_pid_file mesh
verify "without-header" "http://tomcat.${NS}.svc.cluster.local:8080" "kt-connect demo v1"
verify "with-header" "VERSION:ci" "http://tomcat.${NS}.svc.cluster.local:8080" "kt-connect local v2"
success "ktctl mesh test passed"
}
function test_ktctl_preview() {
# Test preview
ktctl -d -n ${NS} -i ${SHADOW_IMAGE} -f preview tomcat-preview --expose 8080 >/tmp/kt-it-preview.log 2>&1 &
wait_for_pod tomcat-preview-kt 1
check_job preview
check_pid_file preview
sleep 3
verify "service-domain" "http://tomcat-preview.${NS}.svc.cluster.local:8080" "kt-connect local v2"
success "ktctl preview test passed"
}
if [ "${1}" = "--help" ]; then
usage
exit 0
elif [ "${1}" = "--cleanup-only" ]; then
CLEANUP_ONLY="Y"
elif [ "${1}" = "--keep-proof" ]; then
KEEP_PROOF="Y"
fi
if [ "${CLEANUP_ONLY}" = "Y" ]; then
cleanup
success "cleanup done"
else
prepare_cluster
test_ktctl_connect
prepare_local
test_ktctl_mesh
test_ktctl_exchange
test_ktctl_preview
cleanup
success "all tests done"
fi