consul/test/integration/connect/envoy/helpers.windows.bash

1195 lines
32 KiB
Bash
Raw Normal View History

Envoy Integration Test Windows (#18007) * [CONSUL-395] Update check_hostport and Usage (#40) * [CONSUL-397] Copy envoy binary from Image (#41) * [CONSUL-382] Support openssl in unique test dockerfile (#43) * [CONSUL-405] Add bats to single container (#44) * [CONSUL-414] Run Prometheus Test Cases and Validate Changes (#46) * [CONSUL-410] Run Jaeger in Single container (#45) * [CONSUL-412] Run test-sds-server in single container (#48) * [CONSUL-408] Clean containers (#47) * [CONSUL-384] Rebase and sync fork (#50) * [CONSUL-415] Create Scenarios Troubleshooting Docs (#49) * [CONSUL-417] Update Docs Single Container (#51) * [CONSUL-428] Add Socat to single container (#54) * [CONSUL-424] Replace pkill in kill_envoy function (#52) * [CONSUL-434] Modify Docker run functions in Helper script (#53) * [CONSUL-435] Replace docker run in set_ttl_check_state & wait_for_agent_service_register functions (#55) * [CONSUL-438] Add netcat (nc) in the Single container Dockerfile (#56) * [CONSUL-429] Replace Docker run with Docker exec (#57) * [CONSUL-436] Curl timeout and run tests (#58) * [CONSUL-443] Create dogstatsd Function (#59) * [CONSUL-431] Update Docs Netcat (#60) * [CONSUL-439] Parse nc Command in function (#61) * [CONSUL-463] Review curl Exec and get_ca_root Func (#63) * [CONSUL-453] Docker hostname in Helper functions (#64) * [CONSUL-461] Test wipe volumes without extra cont (#66) * [CONSUL-454] Check ports in the Server and Agent containers (#65) * [CONSUL-441] Update windows dockerfile with version (#62) * [CONSUL-466] Review case-grpc Failing Test (#67) * [CONSUL-494] Review case-cfg-resolver-svc-failover (#68) * [CONSUL-496] Replace docker_wget & docker_curl (#69) * [CONSUL-499] Cleanup Scripts - Remove nanoserver (#70) * [CONSUL-500] Update Troubleshooting Docs (#72) * [CONSUL-502] Pull & Tag Envoy Windows Image (#73) * [CONSUL-504] Replace docker run in docker_consul (#76) * [CONSUL-505] Change admin_bind * [CONSUL-399] Update envoy to 1.23.1 (#78) * [CONSUL-510] Support case-wanfed-gw on Windows (#79) * [CONSUL-506] Update troubleshooting Documentation (#80) * [CONSUL-512] Review debug_dump_volumes Function (#81) * [CONSUL-514] Add zipkin to Docker Image (#82) * [CONSUL-515] Update Documentation (#83) * [CONSUL-529] Support case-consul-exec (#86) * [CONSUL-530] Update Documentation (#87) * [CONSUL-530] Update default consul version 1.13.3 * [CONSUL-539] Cleanup (#91) * [CONSUL-546] Scripts Clean-up (#92) * [CONSUL-491] Support admin_access_log_path value for Windows (#71) * [CONSUL-519] Implement mkfifo Alternative (#84) * [CONSUL-542] Create OS Specific Files for Envoy Package (#88) * [CONSUL-543] Create exec_supported.go (#89) * [CONSUL-544] Test and Build Changes (#90) * Implement os.DevNull * using mmap instead of disk files * fix import in exec-unix * fix nmap open too many arguemtn * go fmt on file * changelog file * fix go mod * Update .changelog/17694.txt Co-authored-by: Dhia Ayachi <dhia@hashicorp.com> * different mmap library * fix bootstrap json * some fixes * chocolatey version fix and image fix * using different library * fix Map funciton call * fix mmap call * fix tcp dump * fix tcp dump * windows tcp dump * Fix docker run * fix tests * fix go mod * fix version 16.0 * fix version * fix version dev * sleep to debug * fix sleep * fix permission issue * fix permission issue * fix permission issue * fix command * fix command * fix funciton * fix assert config entry status command not found * fix command not found assert_cert_has_cn * fix command not found assert_upstream_missing * fix command not found assert_upstream_missing_once * fix command not found get_upstream_endpoint * fix command not found get_envoy_public_listener_once * fix command not found * fix test cases * windows integration test workflow github * made code similar to unix using npipe * fix go.mod * fix dialing of npipe * dont wait * check size of written json * fix undefined n * running * fix dep * fix syntax error * fix workflow file * windows runner * fix runner * fix from json * fix runs on * merge connect envoy * fix cin path * build * fix file name * fix file name * fix dev build * remove unwanted code * fix upload * fix bin name * fix path * checkout current branch * fix path * fix tests * fix shell bash for windows sh files * fix permission of run-test.sh * removed docker dev * added shell bash for tests * fix tag * fix win=true * fix cd * added dev * fix variable undefined * removed failing tests * fix tcp dump image * fix curl * fix curl * tcp dump path * fix tcpdump path * fix curl * fix curl install * stop removing intermediate containers * fix tcpdump docker image * revert -rm * --rm=false * makeing docker image before * fix tcpdump * removed case consul exec * removed terminating gateway simple * comment case wasm * removed data dog * comment out upload coverage * uncomment case-consul-exec * comment case consul exec * if always * logs * using consul 1.17.0 * fix quotes * revert quotes * redirect to dev null * Revert version * revert consul connect * fix version * removed envoy connect * not using function * change log * docker logs * fix logs * restructure bad authz * rmeoved dev null * output * fix file descriptor * fix cacert * fix cacert * fix ca cert * cacert does not work in windows curl * fix func * removed docker logs * added sleep * fix tls * commented case-consul-exec * removed echo * retry docker consul * fix upload bin * uncomment consul exec * copying consul.exe to docker image * copy fix * fix paths * fix path * github workspace path * latest version * Revert "latest version" This reverts commit 5a7d7b82d9e7553bcb01b02557ec8969f9deba1d. * commented consul exec * added ssl revoke best effort * revert best effort * removed unused files * rename var name and change dir * windows runner * permission * needs setup fix * swtich to github runner * fix file path * fix path * fix path * fix path * fix path * fix path * fix build paths * fix tag * nightly runs * added matrix in github workflow, renamed files * fix job * fix matrix * removed brackes * from json * without using job matrix * fix quotes * revert job matrix * fix workflow * fix comment * added comment * nightly runs * removed datadog ci as it is already measured in linux one * running test * Revert "running test" This reverts commit 7013d15a23732179d18ec5d17336e16b26fab5d4. * pr comment fixes * running test now * running subset of test * running subset of test * job matrix * shell bash * removed bash shell * linux machine for job matrix * fix output * added cat to debug * using ubuntu latest * fix job matrix * fix win true * fix go test * revert job matrix --------- Co-authored-by: Jose Ignacio Lorenzo <74208929+joselo85@users.noreply.github.com> Co-authored-by: Franco Bruno Lavayen <cocolavayen@gmail.com> Co-authored-by: Ivan K Berlot <ivanberlot@gmail.com> Co-authored-by: Ezequiel Fernández Ponce <20102608+ezfepo@users.noreply.github.com> Co-authored-by: joselo85 <joseignaciolorenzo85@gmail.com> Co-authored-by: Ezequiel Fernández Ponce <ezequiel.fernandez@southworks.com> Co-authored-by: Dhia Ayachi <dhia@hashicorp.com>
2023-07-21 14:56:00 +00:00
#!/bin/bash
[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2023-08-11 13:12:13 +00:00
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
Envoy Integration Test Windows (#18007) * [CONSUL-395] Update check_hostport and Usage (#40) * [CONSUL-397] Copy envoy binary from Image (#41) * [CONSUL-382] Support openssl in unique test dockerfile (#43) * [CONSUL-405] Add bats to single container (#44) * [CONSUL-414] Run Prometheus Test Cases and Validate Changes (#46) * [CONSUL-410] Run Jaeger in Single container (#45) * [CONSUL-412] Run test-sds-server in single container (#48) * [CONSUL-408] Clean containers (#47) * [CONSUL-384] Rebase and sync fork (#50) * [CONSUL-415] Create Scenarios Troubleshooting Docs (#49) * [CONSUL-417] Update Docs Single Container (#51) * [CONSUL-428] Add Socat to single container (#54) * [CONSUL-424] Replace pkill in kill_envoy function (#52) * [CONSUL-434] Modify Docker run functions in Helper script (#53) * [CONSUL-435] Replace docker run in set_ttl_check_state & wait_for_agent_service_register functions (#55) * [CONSUL-438] Add netcat (nc) in the Single container Dockerfile (#56) * [CONSUL-429] Replace Docker run with Docker exec (#57) * [CONSUL-436] Curl timeout and run tests (#58) * [CONSUL-443] Create dogstatsd Function (#59) * [CONSUL-431] Update Docs Netcat (#60) * [CONSUL-439] Parse nc Command in function (#61) * [CONSUL-463] Review curl Exec and get_ca_root Func (#63) * [CONSUL-453] Docker hostname in Helper functions (#64) * [CONSUL-461] Test wipe volumes without extra cont (#66) * [CONSUL-454] Check ports in the Server and Agent containers (#65) * [CONSUL-441] Update windows dockerfile with version (#62) * [CONSUL-466] Review case-grpc Failing Test (#67) * [CONSUL-494] Review case-cfg-resolver-svc-failover (#68) * [CONSUL-496] Replace docker_wget & docker_curl (#69) * [CONSUL-499] Cleanup Scripts - Remove nanoserver (#70) * [CONSUL-500] Update Troubleshooting Docs (#72) * [CONSUL-502] Pull & Tag Envoy Windows Image (#73) * [CONSUL-504] Replace docker run in docker_consul (#76) * [CONSUL-505] Change admin_bind * [CONSUL-399] Update envoy to 1.23.1 (#78) * [CONSUL-510] Support case-wanfed-gw on Windows (#79) * [CONSUL-506] Update troubleshooting Documentation (#80) * [CONSUL-512] Review debug_dump_volumes Function (#81) * [CONSUL-514] Add zipkin to Docker Image (#82) * [CONSUL-515] Update Documentation (#83) * [CONSUL-529] Support case-consul-exec (#86) * [CONSUL-530] Update Documentation (#87) * [CONSUL-530] Update default consul version 1.13.3 * [CONSUL-539] Cleanup (#91) * [CONSUL-546] Scripts Clean-up (#92) * [CONSUL-491] Support admin_access_log_path value for Windows (#71) * [CONSUL-519] Implement mkfifo Alternative (#84) * [CONSUL-542] Create OS Specific Files for Envoy Package (#88) * [CONSUL-543] Create exec_supported.go (#89) * [CONSUL-544] Test and Build Changes (#90) * Implement os.DevNull * using mmap instead of disk files * fix import in exec-unix * fix nmap open too many arguemtn * go fmt on file * changelog file * fix go mod * Update .changelog/17694.txt Co-authored-by: Dhia Ayachi <dhia@hashicorp.com> * different mmap library * fix bootstrap json * some fixes * chocolatey version fix and image fix * using different library * fix Map funciton call * fix mmap call * fix tcp dump * fix tcp dump * windows tcp dump * Fix docker run * fix tests * fix go mod * fix version 16.0 * fix version * fix version dev * sleep to debug * fix sleep * fix permission issue * fix permission issue * fix permission issue * fix command * fix command * fix funciton * fix assert config entry status command not found * fix command not found assert_cert_has_cn * fix command not found assert_upstream_missing * fix command not found assert_upstream_missing_once * fix command not found get_upstream_endpoint * fix command not found get_envoy_public_listener_once * fix command not found * fix test cases * windows integration test workflow github * made code similar to unix using npipe * fix go.mod * fix dialing of npipe * dont wait * check size of written json * fix undefined n * running * fix dep * fix syntax error * fix workflow file * windows runner * fix runner * fix from json * fix runs on * merge connect envoy * fix cin path * build * fix file name * fix file name * fix dev build * remove unwanted code * fix upload * fix bin name * fix path * checkout current branch * fix path * fix tests * fix shell bash for windows sh files * fix permission of run-test.sh * removed docker dev * added shell bash for tests * fix tag * fix win=true * fix cd * added dev * fix variable undefined * removed failing tests * fix tcp dump image * fix curl * fix curl * tcp dump path * fix tcpdump path * fix curl * fix curl install * stop removing intermediate containers * fix tcpdump docker image * revert -rm * --rm=false * makeing docker image before * fix tcpdump * removed case consul exec * removed terminating gateway simple * comment case wasm * removed data dog * comment out upload coverage * uncomment case-consul-exec * comment case consul exec * if always * logs * using consul 1.17.0 * fix quotes * revert quotes * redirect to dev null * Revert version * revert consul connect * fix version * removed envoy connect * not using function * change log * docker logs * fix logs * restructure bad authz * rmeoved dev null * output * fix file descriptor * fix cacert * fix cacert * fix ca cert * cacert does not work in windows curl * fix func * removed docker logs * added sleep * fix tls * commented case-consul-exec * removed echo * retry docker consul * fix upload bin * uncomment consul exec * copying consul.exe to docker image * copy fix * fix paths * fix path * github workspace path * latest version * Revert "latest version" This reverts commit 5a7d7b82d9e7553bcb01b02557ec8969f9deba1d. * commented consul exec * added ssl revoke best effort * revert best effort * removed unused files * rename var name and change dir * windows runner * permission * needs setup fix * swtich to github runner * fix file path * fix path * fix path * fix path * fix path * fix path * fix build paths * fix tag * nightly runs * added matrix in github workflow, renamed files * fix job * fix matrix * removed brackes * from json * without using job matrix * fix quotes * revert job matrix * fix workflow * fix comment * added comment * nightly runs * removed datadog ci as it is already measured in linux one * running test * Revert "running test" This reverts commit 7013d15a23732179d18ec5d17336e16b26fab5d4. * pr comment fixes * running test now * running subset of test * running subset of test * job matrix * shell bash * removed bash shell * linux machine for job matrix * fix output * added cat to debug * using ubuntu latest * fix job matrix * fix win true * fix go test * revert job matrix --------- Co-authored-by: Jose Ignacio Lorenzo <74208929+joselo85@users.noreply.github.com> Co-authored-by: Franco Bruno Lavayen <cocolavayen@gmail.com> Co-authored-by: Ivan K Berlot <ivanberlot@gmail.com> Co-authored-by: Ezequiel Fernández Ponce <20102608+ezfepo@users.noreply.github.com> Co-authored-by: joselo85 <joseignaciolorenzo85@gmail.com> Co-authored-by: Ezequiel Fernández Ponce <ezequiel.fernandez@southworks.com> Co-authored-by: Dhia Ayachi <dhia@hashicorp.com>
2023-07-21 14:56:00 +00:00
CONSUL_HOSTNAME=""
MOD_ARG=""
function split_hostport {
local HOSTPORT="$@"
if [[ $HOSTPORT == *":"* ]]; then
MOD_ARG=$( <<< $HOSTPORT sed 's/:/ /' )
fi
}
function get_consul_hostname {
local DC=${1:-primary}
[[ $XDS_TARGET = "client" ]] && CONSUL_HOSTNAME="consul-$DC-client" || CONSUL_HOSTNAME="consul-$DC"
}
# retry based on
# https://github.com/fernandoacorreia/azure-docker-registry/blob/master/tools/scripts/create-registry-server
# under MIT license.
function retry {
local n=1
local max=$1
shift
local delay=$1
shift
local errtrace=0
if grep -q "errtrace" <<<"$SHELLOPTS"
then
errtrace=1
set +E
fi
if [[ $1 == "curl" ]]; then
set -- "${@}" -m 10
elif [[ $1 == "nc" ]]
then
split_hostport $3
set -- "${@:1:2}" $MOD_ARG "${@:4}"
fi
# This if block, was added to check if curl is being executed directly on a test,
# if so, we replace the url parameter with the correct one.
for ((i=1;i<=$max;i++))
do
if "$@"
then
if test $errtrace -eq 1
then
set -E
fi
return 0
else
echo "Command failed. Attempt $i/$max:"
sleep $delay
fi
done
if test $errtrace -eq 1; then
set -E
fi
return 1
}
function retry_default {
local DEFAULT_TOTAL_RETRIES=5
set +E
ret=0
retry $DEFAULT_TOTAL_RETRIES 1 "$@" || ret=1
set -E
return $ret
}
function retry_long {
retry 30 1 "$@"
}
function is_set {
# Arguments:
# $1 - string value to check its truthiness
#
# Return:
# 0 - is truthy (backwards I know but allows syntax like `if is_set <var>` to work)
# 1 - is not truthy
local val=$(tr '[:upper:]' '[:lower:]' <<<"$1")
case $val in
1 | t | true | y | yes)
return 0
;;
*)
return 1
;;
esac
}
function get_cert {
local HOSTPORT=$1
local SERVER_NAME=$2
local CA_FILE=$3
local SNI_FLAG=""
if [ -n "$SERVER_NAME" ]; then
SNI_FLAG="-servername $SERVER_NAME"
fi
CERT=$(openssl s_client -connect $HOSTPORT $SNI_FLAG -showcerts </dev/null)
openssl x509 -noout -text <<<"$CERT"
}
function assert_proxy_presents_cert_uri {
local HOSTPORT=$1
local SERVICENAME=$2
local DC=${3:-primary}
local NS=${4:-default}
local PARTITION=${5:default}
CERT=$(retry_default get_cert $HOSTPORT)
echo "WANT SERVICE: ${PARTITION}/${NS}/${SERVICENAME}"
echo "GOT CERT:"
echo "$CERT"
if [[ -z $PARTITION ]] || [[ $PARTITION = "default" ]]; then
echo "$CERT" | grep -Eo "URI:spiffe://([a-zA-Z0-9-]+).consul/ns/${NS}/dc/${DC}/svc/$SERVICENAME"
else
echo "$CERT" | grep -Eo "URI:spiffe://([a-zA-Z0-9-]+).consul/ap/${PARTITION}/ns/${NS}/dc/${DC}/svc/$SERVICENAME"
fi
}
function assert_dnssan_in_cert {
local HOSTPORT=$1
local DNSSAN=$2
local SERVER_NAME=${3:-$DNSSAN}
CERT=$(retry_default get_cert $HOSTPORT $SERVER_NAME)
echo "WANT DNSSAN: ${DNSSAN} (SNI: ${SERVER_NAME})"
echo "GOT CERT:"
echo "$CERT"
echo "$CERT" | grep -Eo "DNS:${DNSSAN}"
}
function assert_cert_signed_by_ca {
local CA_FILE=$1
local HOSTPORT=$2
local DNSSAN=$3
local SERVER_NAME=${4:-$DNSSAN}
local SNI_FLAG=""
if [ -n "$SERVER_NAME" ]; then
SNI_FLAG="-servername $SERVER_NAME"
fi
# Fix in the CA_FILE parameter: for Windows environments, the root path starts with "/c"
CERT=$(openssl s_client -connect $HOSTPORT $SNI_FLAG -CAfile "/c/$CA_FILE" -showcerts </dev/null)
echo "GOT CERT:"
echo "$CERT"
echo "$CERT" | grep 'Verify return code: 0 (ok)'
}
function assert_cert_has_cn {
local HOSTPORT=$1
local CN=$2
local SERVER_NAME=${3:-$CN}
CERT=$(openssl s_client -connect $HOSTPORT -servername $SERVER_NAME -showcerts </dev/null 2>/dev/null)
echo "WANT CN: ${CN} (SNI: ${SERVER_NAME})"
echo "GOT CERT:"
echo "$CERT"
echo "$CERT" | grep "CN = ${CN}"
}
function get_upstream_endpoint {
local HOSTPORT=$1
local CLUSTER_NAME=$2
run curl -s -f "http://${HOSTPORT}/clusters?format=json"
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output "
.cluster_statuses[]
| select(.name|startswith(\"${CLUSTER_NAME}\"))"
}
function assert_upstream_missing_once {
local HOSTPORT=$1
local CLUSTER_NAME=$2
run get_upstream_endpoint $HOSTPORT $CLUSTER_NAME
[ "$status" -eq 0 ]
echo "$output"
[ "" == "$output" ]
}
function assert_upstream_missing {
local HOSTPORT=$1
local CLUSTER_NAME=$2
run retry_long assert_upstream_missing_once $HOSTPORT $CLUSTER_NAME
echo "OUTPUT: $output $status"
[ "$status" -eq 0 ]
}
function assert_envoy_version {
local ADMINPORT=$1
run retry_default curl -f -s localhost:$ADMINPORT/server_info
[ "$status" -eq 0 ]
# Envoy 1.8.0 returns a plain text line like
# envoy 5d25f466c3410c0dfa735d7d4358beb76b2da507/1.8.0/Clean/DEBUG live 3 3 0
# Later versions return JSON.
if (echo $output | grep '^envoy'); then
VERSION=$(echo $output | cut -d ' ' -f 2)
else
VERSION=$(echo $output | jq -r '.version')
fi
echo "Status=$status"
echo "Output=$output"
echo "---"
echo "Got version=$VERSION"
echo "Want version=$ENVOY_VERSION"
# 1.20.2, 1.19.3 and 1.18.6 are special snowflakes in that the version for
# the release is reported with a '-dev' suffix (eg 1.20.2-dev).
if [ "$ENVOY_VERSION" = "1.20.2" ]; then
ENVOY_VERSION="1.20.2-dev"
elif [ "$ENVOY_VERSION" = "1.19.3" ]; then
ENVOY_VERSION="1.19.3-dev"
elif [ "$ENVOY_VERSION" = "1.18.6" ]; then
ENVOY_VERSION="1.18.6-dev"
fi
echo $VERSION | grep "/$ENVOY_VERSION/"
}
function assert_envoy_expose_checks_listener_count {
local HOSTPORT=$1
local EXPECT_PATH=$2
# scrape this once
BODY=$(get_envoy_expose_checks_listener_once $HOSTPORT)
echo "BODY = $BODY"
CHAINS=$(echo "$BODY" | jq '.active_state.listener.filter_chains | length')
echo "CHAINS = $CHAINS (expect 1)"
[ "${CHAINS:-0}" -eq 1 ]
RANGES=$(echo "$BODY" | jq '.active_state.listener.filter_chains[0].filter_chain_match.source_prefix_ranges | length')
echo "RANGES = $RANGES (expect 3)"
# note: if IPv6 is not supported in the kernel per
# agent/xds:kernelSupportsIPv6() then this will only be 2
[ "${RANGES:-0}" -eq 3 ]
HCM=$(echo "$BODY" | jq '.active_state.listener.filter_chains[0].filters[0]')
HCM_NAME=$(echo "$HCM" | jq -r '.name')
HCM_PATH=$(echo "$HCM" | jq -r '.typed_config.route_config.virtual_hosts[0].routes[0].match.path')
echo "HCM = $HCM"
[ "${HCM_NAME:-}" == "envoy.filters.network.http_connection_manager" ]
[ "${HCM_PATH:-}" == "${EXPECT_PATH}" ]
}
function get_envoy_expose_checks_listener_once {
local HOSTPORT=$1
run curl -m 5 -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output '.configs[] | select(.["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump") | .dynamic_listeners[] | select(.name | startswith("exposed_path_"))'
}
function get_envoy_public_listener_once {
local HOSTPORT=$1
run curl -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output '.configs[] | select(.["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump") | .dynamic_listeners[] | select(.name | startswith("public_listener:"))'
}
function assert_envoy_http_rbac_policy_count {
local HOSTPORT=$1
local EXPECT_COUNT=$2
GOT_COUNT=$(get_envoy_http_rbac_once $HOSTPORT | jq '.rules.policies | length')
echo "GOT_COUNT = $GOT_COUNT"
[ "${GOT_COUNT:-0}" -eq $EXPECT_COUNT ]
}
function get_envoy_http_rbac_once {
local HOSTPORT=$1
run curl -m 5 -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener.filter_chains[0].filters[0].typed_config.http_filters[] | select(.name == "envoy.filters.http.rbac") | .typed_config'
}
function assert_envoy_network_rbac_policy_count {
local HOSTPORT=$1
local EXPECT_COUNT=$2
GOT_COUNT=$(get_envoy_network_rbac_once $HOSTPORT | jq '.rules.policies | length')
echo "GOT_COUNT = $GOT_COUNT"
[ "${GOT_COUNT:-0}" -eq $EXPECT_COUNT ]
}
function get_envoy_network_rbac_once {
local HOSTPORT=$1
run curl -m 5 -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener.filter_chains[0].filters[] | select(.name == "envoy.filters.network.rbac") | .typed_config'
}
function get_envoy_listener_filters {
local HOSTPORT=$1
run retry_default curl -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener | "\(.name) \( .filter_chains[0].filters | map(.name) | join(","))"'
}
function get_envoy_http_filter {
local HOSTPORT=$1
local FILTER_NAME=$2
run retry_default curl -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output ".configs[2].dynamic_listeners[] | .active_state.listener.filter_chains[].filters[] | select(.name == \"envoy.filters.network.http_connection_manager\") | .typed_config.http_filters[] | select(.name == \"${FILTER_NAME}\")"
}
function get_envoy_http_filters {
local HOSTPORT=$1
run retry_default curl -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output '.configs[2].dynamic_listeners[].active_state.listener | "\(.name) \( .filter_chains[0].filters[] | select(.name == "envoy.filters.network.http_connection_manager") | .typed_config.http_filters | map(.name) | join(","))"'
}
function get_envoy_dynamic_cluster_once {
local HOSTPORT=$1
local NAME_PREFIX=$2
run curl -m 5 -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output ".configs[] | select (.[\"@type\"] == \"type.googleapis.com/envoy.admin.v3.ClustersConfigDump\") | .dynamic_active_clusters[] | select(.cluster.name | startswith(\"${NAME_PREFIX}\"))"
}
function assert_envoy_dynamic_cluster_exists_once {
local HOSTPORT=$1
local NAME_PREFIX=$2
local EXPECT_SNI=$3
BODY="$(get_envoy_dynamic_cluster_once $HOSTPORT $NAME_PREFIX)"
[ -n "$BODY" ]
SNI="$(echo "$BODY" | jq --raw-output ".cluster.transport_socket.typed_config.sni | select(. | startswith(\"${EXPECT_SNI}\"))")"
[ -n "$SNI" ]
}
function assert_envoy_dynamic_cluster_exists {
local HOSTPORT=$1
local NAME_PREFIX=$2
local EXPECT_SNI=$3
run retry_long assert_envoy_dynamic_cluster_exists_once $HOSTPORT $NAME_PREFIX $EXPECT_SNI
[ "$status" -eq 0 ]
}
function get_envoy_cluster_config {
local HOSTPORT=$1
local CLUSTER_NAME=$2
run retry_default curl -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output "
.configs[1].dynamic_active_clusters[]
| select(.cluster.name|startswith(\"${CLUSTER_NAME}\"))
| .cluster
"
}
function get_envoy_stats_flush_interval {
local HOSTPORT=$1
run retry_default curl -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
#echo "$output" > /workdir/s1_envoy_dump.json
echo "$output" | jq --raw-output '.configs[0].bootstrap.stats_flush_interval'
}
# snapshot_envoy_admin is meant to be used from a teardown scriptlet from the host.
function snapshot_envoy_admin {
local HOSTPORT=$1
local ENVOY_NAME=$2
local DC=${3:-primary}
local OUTDIR="${LOG_DIR}/envoy-snapshots/${DC}/${ENVOY_NAME}"
mkdir -p "${OUTDIR}"
docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/config_dump" > "${OUTDIR}/config_dump.json"
docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/clusters?format=json" > "${OUTDIR}/clusters.json"
docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/stats" > "${OUTDIR}/stats.txt"
docker_consul_exec "$DC" bash -c "curl -s http://${HOSTPORT}/stats/prometheus" > "${OUTDIR}/stats_prometheus.txt"
}
function reset_envoy_metrics {
local HOSTPORT=$1
curl -m 5 -s -f -XPOST $HOSTPORT/reset_counters
return $?
}
function get_all_envoy_metrics {
local HOSTPORT=$1
curl -m 5 -s -f $HOSTPORT/stats
return $?
}
function get_envoy_metrics {
local HOSTPORT=$1
local METRICS=$2
get_all_envoy_metrics $HOSTPORT | grep "$METRICS"
}
function assert_upstream_has_endpoint_port {
local HOSTPORT=$1
local CLUSTER_NAME=$2
local PORT_VALUE=$3
run retry_long assert_upstream_has_endpoint_port_once $HOSTPORT $CLUSTER_NAME $PORT_VALUE
[ "$status" -eq 0 ]
}
function get_upstream_endpoint_in_status_count {
local HOSTPORT=$1
local CLUSTER_NAME=$2
local HEALTH_STATUS=$3
run curl -m 5 -s -f "http://${HOSTPORT}/clusters?format=json"
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output "
.cluster_statuses[]
| select(.name|startswith(\"${CLUSTER_NAME}\"))
| [.host_statuses[].health_status.eds_health_status]
| [select(.[] == \"${HEALTH_STATUS}\")]
| length"
}
function assert_upstream_has_endpoints_in_status_once {
local HOSTPORT=$1
local CLUSTER_NAME=$2
local HEALTH_STATUS=$3
local EXPECT_COUNT=$4
GOT_COUNT=$(get_upstream_endpoint_in_status_count $HOSTPORT $CLUSTER_NAME $HEALTH_STATUS)
[ "$GOT_COUNT" -eq $EXPECT_COUNT ]
}
function assert_upstream_has_endpoints_in_status {
local HOSTPORT=$1
local CLUSTER_NAME=$2
local HEALTH_STATUS=$3
local EXPECT_COUNT=$4
run retry_long assert_upstream_has_endpoints_in_status_once $HOSTPORT $CLUSTER_NAME $HEALTH_STATUS $EXPECT_COUNT
[ "$status" -eq 0 ]
}
function assert_envoy_metric {
set -eEuo pipefail
local HOSTPORT=$1
local METRIC=$2
local EXPECT_COUNT=$3
METRICS=$(get_envoy_metrics $HOSTPORT "$METRIC")
if [ -z "${METRICS}" ]; then
echo "Metric not found" 1>&2
return 1
fi
GOT_COUNT=$(awk -F: '{print $2}' <<<"$METRICS" | head -n 1 | tr -d ' ')
if [ -z "$GOT_COUNT" ]; then
echo "Couldn't parse metric count" 1>&2
return 1
fi
if [ $EXPECT_COUNT -ne $GOT_COUNT ]; then
echo "$METRIC - expected count: $EXPECT_COUNT, actual count: $GOT_COUNT" 1>&2
return 1
fi
}
function assert_envoy_metric_at_least {
set -eEuo pipefail
local HOSTPORT=$1
local METRIC=$2
local EXPECT_COUNT=$3
METRICS=$(get_envoy_metrics $HOSTPORT "$METRIC")
if [ -z "${METRICS}" ]; then
echo "Metric not found" 1>&2
return 1
fi
GOT_COUNT=$(awk -F: '{print $2}' <<<"$METRICS" | head -n 1 | tr -d ' ')
if [ -z "$GOT_COUNT" ]; then
echo "Couldn't parse metric count" 1>&2
return 1
fi
if [ $EXPECT_COUNT -gt $GOT_COUNT ]; then
echo "$METRIC - expected >= count: $EXPECT_COUNT, actual count: $GOT_COUNT" 1>&2
return 1
fi
}
function assert_envoy_aggregate_metric_at_least {
set -eEuo pipefail
local HOSTPORT=$1
local METRIC=$2
local EXPECT_COUNT=$3
METRICS=$(get_envoy_metrics $HOSTPORT "$METRIC")
if [ -z "${METRICS}" ]; then
echo "Metric not found" 1>&2
return 1
fi
GOT_COUNT=$(awk '{ sum += $2 } END { print sum }' <<<"$METRICS")
if [ -z "$GOT_COUNT" ]; then
echo "Couldn't parse metric count" 1>&2
return 1
fi
if [ $EXPECT_COUNT -gt $GOT_COUNT ]; then
echo "$METRIC - expected >= count: $EXPECT_COUNT, actual count: $GOT_COUNT" 1>&2
return 1
fi
}
function get_healthy_service_count {
local SERVICE_NAME=$1
local DC=$2
local NS=$3
local AP=$4
local PEER_NAME=$5
run curl -m 5 -s -f ${HEADERS} "consul-${DC}-client:8500/v1/health/connect/${SERVICE_NAME}?passing&ns=${NS}&partition=${AP}&peer=${PEER_NAME}"
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output '. | length'
}
function assert_alive_wan_member_count {
local DC=$1
local EXPECT_COUNT=$2
run retry_long assert_alive_wan_member_count_once $DC $EXPECT_COUNT
[ "$status" -eq 0 ]
}
function assert_alive_wan_member_count_once {
local DC=$1
local EXPECT_COUNT=$2
GOT_COUNT=$(get_alive_wan_member_count $DC)
[ "$GOT_COUNT" -eq "$EXPECT_COUNT" ]
}
function get_alive_wan_member_count {
local DC=$1
run retry_default curl -sL -f "consul-${DC}-server:8500/v1/agent/members?wan=1"
[ "$status" -eq 0 ]
# echo "$output" >&3
echo "$output" | jq '.[] | select(.Status == 1) | .Name' | wc -l
}
function assert_service_has_healthy_instances_once {
local SERVICE_NAME=$1
local EXPECT_COUNT=$2
local DC=${3:-primary}
local NS=${4:-}
local AP=${5:-}
local PEER_NAME=${6:-}
GOT_COUNT=$(get_healthy_service_count "$SERVICE_NAME" "$DC" "$NS" "$AP" "$PEER_NAME")
[ "$GOT_COUNT" -eq $EXPECT_COUNT ]
}
function assert_service_has_healthy_instances {
local SERVICE_NAME=$1
local EXPECT_COUNT=$2
local DC=${3:-primary}
local NS=${4:-}
local AP=${5:-}
local PEER_NAME=${6:-}
run retry_long assert_service_has_healthy_instances_once "$SERVICE_NAME" "$EXPECT_COUNT" "$DC" "$NS" "$AP" "$PEER_NAME"
[ "$status" -eq 0 ]
}
function check_intention {
local SOURCE=$1
local DESTINATION=$2
get_consul_hostname primary
curl -m 5 -s -f "${CONSUL_HOSTNAME}:8500/v1/connect/intentions/check?source=${SOURCE}&destination=${DESTINATION}" | jq ".Allowed"
}
function assert_intention_allowed {
local SOURCE=$1
local DESTINATION=$2
run check_intention "${SOURCE}" "${DESTINATION}"
[ "$status" -eq 0 ]
[ "$output" = "true" ]
}
function assert_intention_denied {
local SOURCE=$1
local DESTINATION=$2
run check_intention "${SOURCE}" "${DESTINATION}"
[ "$status" -eq 0 ]
[ "$output" = "false" ]
}
function docker_consul {
local DC=$1
shift 1
retry_default docker_exec envoy_consul-${DC}_1 "$@"
}
function docker_consul_for_proxy_bootstrap {
local DC=$1
shift 1
local CONTAINER_NAME="$SINGLE_CONTAINER_BASE_NAME"-"$DC"_1
docker.exe exec -i $CONTAINER_NAME bash.exe -c "$@"
}
function docker_exec {
if ! docker.exe exec -i "$@"; then
echo "Failed to execute: docker exec -i $@" 1>&2
return 1
fi
}
function docker_consul_exec {
local DC=$1
shift 1
docker_exec envoy_consul-${DC}_1 "$@"
}
function kill_envoy {
local BOOTSTRAP_NAME=$1
local DC=${2:-primary}
PORT=$( cat /c/workdir/$DC/envoy/${BOOTSTRAP_NAME}-bootstrap.json | jq .admin.address.socket_address.port_value )
PID=$( netstat -qo | grep "127.0.0.1:$PORT" | sed -r "s/.* //g" )
tskill $PID
}
function must_match_in_statsd_logs {
local DC=${2:-primary}
local FILE="/c/workdir/${DC}/statsd/statsd.log"
COUNT=$( grep -Ec $1 $FILE )
echo "COUNT of '$1' matches: $COUNT"
[ "$COUNT" -gt "0" ]
}
function must_match_in_prometheus_response {
run curl -m 5 -f -s $1/metrics
COUNT=$( echo "$output" | grep -Ec $2 )
echo "OUTPUT head -n 10"
echo "$output" | head -n 10
echo "COUNT of '$2' matches: $COUNT"
[ "$status" == 0 ]
[ "$COUNT" -gt "0" ]
}
function must_match_in_stats_proxy_response {
run curl -m 5 -f -s $1/$2
COUNT=$( echo "$output" | grep -Ec $3 )
echo "OUTPUT head -n 10"
echo "$output" | head -n 10
echo "COUNT of '$3' matches: $COUNT"
[ "$status" == 0 ]
[ "$COUNT" -gt "0" ]
}
# must_fail_tcp_connection checks that a request made through an upstream fails,
# probably due to authz being denied if all other tests passed already. Although
# we are using curl, this only works as expected for TCP upstreams as we are
# checking TCP-level errors. HTTP upstreams will return a valid 503 generated by
# Envoy rather than a connection-level error.
function must_fail_tcp_connection {
# Attempt to curl through upstream
run curl -m 5 --no-keepalive -s -v -f -d hello $1
echo "OUTPUT $output"
# Should fail during handshake and return "got nothing" error
[ "$status" == "52" ]
# Verbose output should enclude empty reply
echo "$output" | grep 'Empty reply from server'
}
function must_pass_tcp_connection {
run curl -m 5 --no-keepalive -s -f -d hello $1
echo "OUTPUT $output"
[ "$status" == "0" ]
[ "$output" = "hello" ]
}
# must_fail_http_connection see must_fail_tcp_connection but this expects Envoy
# to generate a 503 response since the upstreams have refused connection.
function must_fail_http_connection {
# Attempt to curl through upstream
run curl -m 5 --no-keepalive -s -i -d hello "$1"
echo "OUTPUT $output"
[ "$status" == "0" ]
local expect_response="${2:-403 Forbidden}"
# Should fail request with 503
echo "$output" | grep "${expect_response}"
}
# must_pass_http_request allows you to craft a specific http request to assert
# that envoy will NOT reject the request. Primarily of use for testing L7
# intentions.
function must_pass_http_request {
local METHOD=$1
local URL=$2
local DEBUG_HEADER_VALUE="${3:-""}"
local extra_args
if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then
extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}"
fi
case "$METHOD" in
GET) ;;
DELETE)
extra_args="$extra_args -X${METHOD}"
;;
PUT | POST)
extra_args="$extra_args -d'{}' -X${METHOD}"
;;
*)
return 1
;;
esac
run curl -m 5 --no-keepalive -v -s -f $extra_args "$URL"
[ "$status" == 0 ]
}
# must_fail_http_request allows you to craft a specific http request to assert
# that envoy will reject the request. Primarily of use for testing L7
# intentions.
function must_fail_http_request {
local METHOD=$1
local URL=$2
local DEBUG_HEADER_VALUE="${3:-""}"
local extra_args
if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then
extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}"
fi
case "$METHOD" in
HEAD)
extra_args="$extra_args -I"
;;
GET) ;;
DELETE)
extra_args="$extra_args -X${METHOD}"
;;
PUT | POST)
extra_args="$extra_args -d'{}' -X${METHOD}"
;;
*)
return 1
;;
esac
# Attempt to curl through upstream
run curl -m 5 --no-keepalive -s -i $extra_args "$URL"
echo "OUTPUT $output"
echo "$output" | grep "403 Forbidden"
}
function upsert_config_entry {
local DC="$1"
local BODY="$2"
echo "$BODY" | docker_consul "$DC" consul config write -
}
function gen_envoy_bootstrap {
SERVICE=$1
ADMIN_PORT=$2
DC=${3:-primary}
IS_GW=${4:-0}
EXTRA_ENVOY_BS_ARGS="${5-}"
ADMIN_HOST="0.0.0.0"
PROXY_ID="$SERVICE"
if ! is_set "$IS_GW"; then
PROXY_ID="$SERVICE-sidecar-proxy"
ADMIN_HOST="127.0.0.1"
fi
if output=$(docker_consul_for_proxy_bootstrap $DC "consul connect envoy -bootstrap \
-proxy-id $PROXY_ID \
-envoy-version "$ENVOY_VERSION" \
-http-addr envoy_consul-${DC}_1:8500 \
-grpc-addr envoy_consul-${DC}_1:8502 \
-admin-access-log-path="C:/envoy/envoy.log" \
-admin-bind $ADMIN_HOST:$ADMIN_PORT ${EXTRA_ENVOY_BS_ARGS} \
> /c/workdir/${DC}/envoy/${SERVICE}-bootstrap.json"); then
# All OK, write config to file
echo $output
#echo "$output" > /c/workdir/${DC}/envoy/$SERVICE-bootstrap.json
else
status=$?
# Command failed, instead of swallowing error (printed on stdout by docker
# it seems) by writing it to file, echo it
echo "$output"
#return $status
fi
}
function read_config_entry {
local KIND=$1
local NAME=$2
local DC=${3:-primary}
get_consul_hostname $DC
docker_consul_exec "$DC" bash -c "consul config read -kind $KIND -name $NAME -http-addr=\"$CONSUL_HOSTNAME:8500\""
}
function wait_for_namespace {
local NS="${1}"
local DC=${2:-primary}
get_consul_hostname $DC
retry_default docker_consul_exec "$DC" bash -c "curl -sLf http://${CONSUL_HOSTNAME}:8500/v1/namespace/${NS} >/dev/null"
}
function wait_for_config_entry {
retry_default read_config_entry "$@"
}
function assert_config_entry_status {
local TYPE="$1"
local STATUS="$2"
local REASON="$3"
local DC="$4"
local KIND="$5"
local NAME="$6"
local NS=${7:-}
local AP=${8:-}
local PEER=${9:-}
status=$(curl -s -f "consul-${DC}-client:8500/v1/config/${KIND}/${NAME}?passing&ns=${NS}&partition=${AP}&peer=${PEER}" | jq ".Status.Conditions[] | select(.Type == \"$TYPE\" and .Status == \"$STATUS\" and .Reason == \"$REASON\")")
[ -n "$status" ]
}
function delete_config_entry {
local KIND=$1
local NAME=$2
get_consul_hostname primary
retry_default curl -sL -XDELETE "http://${CONSUL_HOSTNAME}:8500/v1/config/${KIND}/${NAME}"
}
function register_services {
local DC=${1:-primary}
wait_for_leader "$DC"
docker_consul_exec ${DC} bash -c "consul services register workdir/${DC}/register/service_*.hcl"
}
# wait_for_leader waits until a leader is elected.
# Its first argument must be the datacenter name.
function wait_for_leader {
get_consul_hostname primary
retry_default docker_consul_exec "$1" bash -c "[[ $(curl --fail -sS http://${CONSUL_HOSTNAME}:8500/v1/status/leader) ]]"
}
function setup_upsert_l4_intention {
local SOURCE=$1
local DESTINATION=$2
local ACTION=$3
get_consul_hostname primary
retry_default docker_consul_exec primary bash -c "curl -sL -X PUT -d '{\"Action\": \"${ACTION}\"}' 'http://${CONSUL_HOSTNAME}:8500/v1/connect/intentions/exact?source=${SOURCE}&destination=${DESTINATION}'"
}
function upsert_l4_intention {
local SOURCE=$1
local DESTINATION=$2
local ACTION=$3
get_consul_hostname primary
retry_default curl -sL -XPUT "http://${CONSUL_HOSTNAME}:8500/v1/connect/intentions/exact?source=${SOURCE}&destination=${DESTINATION}" \
-d"{\"Action\": \"${ACTION}\"}" >/dev/null
}
function get_ca_root {
get_consul_hostname primary
curl -s -f "http://${CONSUL_HOSTNAME}:8500/v1/connect/ca/roots" | jq -r ".Roots[0].RootCert"
}
function wait_for_agent_service_register {
local SERVICE_ID=$1
local DC=${2:-primary}
get_consul_hostname $DC
retry_default docker_consul_exec "$DC" bash -c "curl -sLf 'http://${CONSUL_HOSTNAME}:8500/v1/agent/service/${SERVICE_ID}' >/dev/null"
}
function set_ttl_check_state {
local CHECK_ID=$1
local CHECK_STATE=$2
local DC=${3:-primary}
get_consul_hostname $DC
case "$CHECK_STATE" in
pass) ;;
warn) ;;
fail) ;;
*)
echo "invalid ttl check state '${CHECK_STATE}'" >&2
return 1
;;
esac
retry_default docker_consul_exec "$DC" bash -c "curl -sL -XPUT 'http://${CONSUL_HOSTNAME}:8500/v1/agent/check/warn/${CHECK_ID}' >/dev/null"
}
function get_upstream_fortio_name {
local HOST=$1
local PORT=$2
local PREFIX=$3
local DEBUG_HEADER_VALUE="${4:-""}"
local extra_args
if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then
extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}"
fi
# split proto if https:// is at the front of the host since the --resolve
# string needs just a bare host.
local PROTO=""
local CA_FILE=""
if [ "${HOST:0:8}" = "https://" ]; then
HOST="${HOST:8}"
PROTO="https://"
# Fix in the CA_FILE parameter: for Windows environments, the root path starts with "/c"
extra_args="${extra_args} --cacert /c/workdir/test-sds-server/certs/ca-root.crt"
fi
# We use --resolve instead of setting a Host header since we need the right
# name to be sent for SNI in some cases too.
run retry_default curl --ssl-revoke-best-effort -v -s -f --resolve "${HOST}:${PORT}:127.0.0.1" $extra_args \
"${PROTO}${HOST}:${PORT}${PREFIX}/debug?env=dump"
# Useful Debugging but breaks the expectation that the value output is just
# the grep output when things don't fail
if [ "$status" != 0 ]; then
echo "GOT FORTIO OUTPUT: $output"
fi
[ "$status" == 0 ]
echo "$output" | grep -E "^FORTIO_NAME="
}
function get_upstream_endpoint_port {
local HOSTPORT=$1
local CLUSTER_NAME=$2
local PORT_VALUE=$3
run curl -s -f "http://${HOSTPORT}/clusters?format=json"
[ "$status" -eq 0 ]
echo "$output" | jq --raw-output "
.cluster_statuses[]
| select(.name|startswith(\"${CLUSTER_NAME}\"))
| [.host_statuses[].address.socket_address.port_value]
| [select(.[] == ${PORT_VALUE})]
| length"
}
function assert_upstream_has_endpoint_port_once {
local HOSTPORT=$1
local CLUSTER_NAME=$2
local PORT_VALUE=$3
GOT_COUNT=$(get_upstream_endpoint_port $HOSTPORT $CLUSTER_NAME $PORT_VALUE)
[ "$GOT_COUNT" -eq 1 ]
}
function assert_expected_fortio_name {
local EXPECT_NAME=$1
local HOST=${2:-"localhost"}
local PORT=${3:-5000}
local URL_PREFIX=${4:-""}
local DEBUG_HEADER_VALUE="${5:-""}"
run get_upstream_fortio_name ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}"
echo "GOT: $output"
[ "$status" == 0 ]
[ "$output" == "FORTIO_NAME=${EXPECT_NAME}" ]
}
function assert_expected_fortio_name_pattern {
local EXPECT_NAME_PATTERN=$1
local HOST=${2:-"localhost"}
local PORT=${3:-5000}
local URL_PREFIX=${4:-""}
local DEBUG_HEADER_VALUE="${5:-""}"
GOT=$(get_upstream_fortio_name ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}")
if [[ "$GOT" =~ $EXPECT_NAME_PATTERN ]]; then
:
else
echo "expected name pattern: $EXPECT_NAME_PATTERN, actual name: $GOT" 1>&2
return 1
fi
}
function get_upstream_fortio_host_header {
local HOST=$1
local PORT=$2
local PREFIX=$3
local DEBUG_HEADER_VALUE="${4:-""}"
local extra_args
if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then
extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}"
fi
run retry_default curl -v -s -f -H"Host: ${HOST}" $extra_args \
"localhost:${PORT}${PREFIX}/debug"
[ "$status" == 0 ]
echo "$output" | grep -E "^Host: "
}
function assert_expected_fortio_host_header {
local EXPECT_HOST=$1
local HOST=${2:-"localhost"}
local PORT=${3:-5000}
local URL_PREFIX=${4:-""}
local DEBUG_HEADER_VALUE="${5:-""}"
GOT=$(get_upstream_fortio_host_header ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}")
if [ "$GOT" != "Host: ${EXPECT_HOST}" ]; then
echo "expected Host header: $EXPECT_HOST, actual Host header: $GOT" 1>&2
return 1
fi
}
function create_peering {
local GENERATE_PEER=$1
local ESTABLISH_PEER=$2
run curl -m 5 -sL -XPOST "http://consul-${GENERATE_PEER}-client:8500/v1/peering/token" -d"{ \"PeerName\" : \"${GENERATE_PEER}-to-${ESTABLISH_PEER}\" }"
# echo "$output" >&3
[ "$status" == 0 ]
local token
token="$(echo "$output" | jq -r .PeeringToken)"
[ -n "$token" ]
run curl -m 5 -sLv -XPOST "http://consul-${ESTABLISH_PEER}-client:8500/v1/peering/establish" -d"{ \"PeerName\" : \"${ESTABLISH_PEER}-to-${GENERATE_PEER}\", \"PeeringToken\" : \"${token}\" }"
# echo "$output" >&3
[ "$status" == 0 ]
}
function assert_service_has_imported {
local DC=${1:-primary}
local SERVICE_NAME=$2
local PEER_NAME=$3
run curl -s -f "http://consul-${DC}-client:8500/v1/peering/${PEER_NAME}"
[ "$status" == 0 ]
echo "$output" | jq --raw-output '.StreamStatus.ImportedServices' | grep -e "${SERVICE_NAME}"
if [ $? -ne 0 ]; then
echo "Error finding service: ${SERVICE_NAME}"
return 1
fi
}
function get_lambda_envoy_http_filter {
local HOSTPORT=$1
local NAME_PREFIX=$2
run retry_default curl -s -f $HOSTPORT/config_dump
[ "$status" -eq 0 ]
# get the full http filter object so the individual fields can be validated.
echo "$output" | jq --raw-output ".configs[2].dynamic_listeners[] | .active_state.listener.filter_chains[].filters[] | select(.name == \"envoy.filters.network.http_connection_manager\") | .typed_config.http_filters[] | select(.name == \"envoy.filters.http.aws_lambda\") | .typed_config"
}
function register_lambdas {
local DC=${1:-primary}
# register lambdas to the catalog
for f in $(find workdir/${DC}/register -type f -name 'lambda_*.json'); do
retry_default curl -sL -XPUT -d @${f} "http://localhost:8500/v1/catalog/register" >/dev/null && \
echo "Registered Lambda: $(jq -r .Service.Service $f)"
done
# write service-defaults config entries for lambdas
for f in $(find workdir/${DC}/register -type f -name 'service_defaults_*.json'); do
varsub ${f} AWS_LAMBDA_REGION AWS_LAMBDA_ARN
retry_default curl -sL -XPUT -d @${f} "http://localhost:8500/v1/config" >/dev/null && \
echo "Wrote config: $(jq -r '.Kind + " / " + .Name' $f)"
done
}
function assert_lambda_envoy_dynamic_cluster_exists {
local HOSTPORT=$1
local NAME_PREFIX=$2
local BODY=$(get_envoy_dynamic_cluster_once $HOSTPORT $NAME_PREFIX)
[ -n "$BODY" ]
[ "$(echo $BODY | jq -r '.cluster.transport_socket.typed_config.sni')" == '*.amazonaws.com' ]
}
function assert_lambda_envoy_dynamic_http_filter_exists {
local HOSTPORT=$1
local NAME_PREFIX=$2
local ARN=$3
local FILTER=$(get_lambda_envoy_http_filter $HOSTPORT $NAME_PREFIX)
[ -n "$FILTER" ]
[ "$(echo $FILTER | jq -r '.arn')" == "$ARN" ]
}
function varsub {
local file=$1
shift
for v in "$@"; do
sed -i "s/\${$v}/${!v}/g" $file
done
}
function get_url_header {
local URL=$1
local HEADER=$2
run curl -s -f -X GET -I "${URL}"
[ "$status" == 0 ]
RESP=$(echo "$output" | tr -d '\r')
RESP=$(echo "$RESP" | grep -E "^${HEADER}: ")
RESP=$(echo "$RESP" | sed "s/^${HEADER}: //g")
echo "$RESP"
}
function assert_url_header {
local URL=$1
local HEADER=$2
local VALUE=$3
run get_url_header "$URL" "$HEADER"
[ "$status" == 0 ]
[ "$VALUE" = "$output" ]
}
# assert_upstream_message asserts both the returned code
# and message from upstream service
function assert_upstream_message {
local HOSTPORT=$1
run curl -s -d hello localhost:$HOSTPORT
if [ "$status" -ne 0 ]; then
echo "Command failed"
return 1
fi
if (echo $output | grep 'hello'); then
return 0
fi
echo "expected message not found in $output"
return 1
}