diff --git a/ci-automation/ci_automation_common.sh b/ci-automation/ci_automation_common.sh index 355a52ce27..32b9d4a4b2 100644 --- a/ci-automation/ci_automation_common.sh +++ b/ci-automation/ci_automation_common.sh @@ -311,7 +311,7 @@ function url_from_template() { # Puts a secret into a file, while trying for the secret to not end up # on a filesystem at all. A path to the file with the secret in /proc -# in put into the chosen variable. The secret is assumed to be +# is put into the chosen variable. The secret is assumed to be # base64-encoded. # # Typical use: @@ -328,6 +328,10 @@ function secret_to_file() { local -n config_ref="${config_var_name}" local fd + # Open "${tmpfile}" file for reading and writing on file + # descriptor that bash allocates and stores in fd. + # + # https://www.gnu.org/software/bash/manual/html_node/Redirections.html exec {fd}<>"${tmpfile}" rm -f "${tmpfile}" echo "${secret}" | base64 --decode >&${fd} diff --git a/ci-automation/new_vendor.sh b/ci-automation/new_vendor.sh new file mode 100755 index 0000000000..2f2d6004b7 --- /dev/null +++ b/ci-automation/new_vendor.sh @@ -0,0 +1,242 @@ +#!/bin/bash +# Copyright (c) 2021 The Flatcar Maintainers. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -euo pipefail + +# Test execution script for the azure vendor image. +# This script is supposed to run in the mantle container. + +source ci-automation/vendor_test.sh + +function generate_broken_test_tapfile { + local error_msg="${1}"; shift + echo "1..1" > "${CIA_TAPFILE}" + echo "not ok - all ${CNV_PLATFORM:-(unknown platform, define CNV_PLATFORM!)} tests" >> "${CIA_TAPFILE}" + echo " ---" >> "${CIA_TAPFILE}" + echo " ERROR: ${error_msg}" | tee -a "${CIA_TAPFILE}" + echo " ..." >> "${CIA_TAPFILE}" +} + +function generate_broken_test_tapfile_and_die { + generate_broken_test_tapfile "${@}" + break_retest_cycle + exit 1 +} + +function generate_fail_tapfile() { + local tapfile="${1}"; shift + # rest of the args are test names + echo "1..${#@}" >"${tapfile}" + printf 'not ok - %s\n' "${@}" >>"${tapfile}" +} + +function check_vars { + if ! declare -p "${@}" >/dev/null 2>&1; then + return 1 + fi + return 0 +} + +function check_funcs { + if ! declare -pF "${@}" >/dev/null 2>&1; then + return 1 + fi + return 0 +} + +CNVI_PHASE='pre-run' +CNVI_ALL_TESTS=( "${@}" ) + +function handle_setup_failures() { + local error_msg + case "${CNVI_PHASE}" in + pre-run) + error_msg='Something failed before running the setup' + ;; + setup) + error_msg='Setup failed' + ;; + *) + return 0; + ;; + esac + # We didn't even reach kola invocation. Let's create a tapfile + # with all the tests marked as a failure. This can be done only if + # the query_kola_tests function and some output variables were + # defined, though. That means that vendor tests should define them + # as early as possible. + if ! check_vars CNV_PLATFORM CNV_MAIN_INSTANCE CNV_EXTRA_INSTANCES CNV_EXTRA_INSTANCE_TESTS; then + echo "handle_setup_failures: '${CIA_TESTSCRIPT}' did not define all the required variables to handle the setup failure" + return 0 + fi + + local -a instance_tests + local -a all_tests + local other_tests_for_fgrep + local instance + + function query_kola_tests { + shift + kola list --platform="${CNV_PLATFORM}" --filter "${@}" + } + + instance_tests=() + all_tests=() + if [[ "${CIA_FIRST_RUN}" -eq 1 ]]; then + # The "-t" option strips the delimiter. "mapfile" clears the + # instance_tests array before assigning to it. + mapfile -t instance_tests < <(run_query_kola_tests "${CNV_MAIN_INSTANCE}" "${CNVI_ALL_TESTS[@]}") + all_tests+=( "${instance_tests[@]}" ) + + other_tests_for_fgrep="$(printf '%s\n' "${CNVI_EXTRA_INSTANCE_TESTS[@]}")" + for instance in "${CNVI_EXTRA_INSTANCES[@]}"; do + mapfile -t instance_tests < <(run_query_kola_tests "${instance}" "${CNVI_ALL_TESTS[@]}" | grep --only-matching --fixed-strings "${other_tests_for_fgrep}" || :) + all_tests+=( "${instance_tests[@]/#/extra_test.[${instance}].}" ) + done + else + all_tests=( "${CNVI_ALL_TESTS[@]}" ) + fi + + unset -f query_kola_tests + + generate_fail_tapfile "${CIA_TAPFILE}" "${all_tests[@]}" + return 0 +} +trap handle_setup_failures ERR + +function ensure_arch { + local arch + for arch; do + if [[ "${CIA_ARCH}" == "${arch}" ]]; then + return 0 + fi + done + generate_broken_test_tapfile_and_die "${CIA_ARCH} tests not supported on ${CNV_PLATFORM}" +} + +function ensure_tests { + local kola_test + for kola_test in "${CNVI_ALL_TESTS[@]}"; do + if [[ "${kola_test}" = '*' ]]; then + CNVI_ALL_TESTS=( "${@}" ) + return 0 + fi + done + local sup_kola_test ok + for kola_test in "${CNVI_ALL_TESTS[@]}"; do + ok= + for sup_kola_test; do + if [[ "${kola_test}" = "${sup_kola_test}" ]] || [[ "${kola_test}" = 'extra-test.['*"].${sup_kola_test}" ]]; then + ok=x + break + fi + if [[ -z "${ok}" ]]; then + generate_broken_test_tapfile_and_die "'${kola_test}' test case is not supported in ${CIA_TESTSCRIPT}" + fi + done + done + return 0 +} + +function run_default_kola_tests { + local variables=( + CNV_MAIN_INSTANCE + CNV_EXTRA_INSTANCES + CNV_EXTRA_INSTANCE_TESTS + CNV_PLATFORM + ) + local funcs=( + get_kola_args + failible_setup + ) + local f + + if ! check_vars "${variables[@]}"; then + generate_broken_test_tapfile_and_die "At least one of ${variables[@]} variables is not defined." + fi + if ! check_funcs "${funcs[@]}"; then + generate_broken_test_tapfile_and_die "At least one of ${funcs[@]} functions is not defined." + fi + for f in query_kola_tests run_kola_tests; do + if check_funcs "${f}"; then + generate_broken_test_tapfile_and_die "Function ${f} can't be defined, it will be clobbered by us." + fi + done + + if [[ -n "${CNV_SUPPORTED_TESTS[@]:-}" ]]; then + ensure_tests "${CNV_SUPPORTED_TESTS[@]}" + fi + + if [[ -n "${CNV_SUPPORTED_ARCH[@]:-}" ]]; then + ensure_arch "${CNV_SUPPORTED_ARCH[@]}" + fi + + CNVI_PHASE='setup' + failible_setup + CNVI_PHASE='run' + + function query_kola_tests { + shift + kola list --platform="${CNV_PLATFORM}" --filter "${@}" + } + + function run_kola_tests { + local instance_type="${1}"; shift + local instance_tapfile="${1}"; shift + local -a kola_args kola_tests + + mapfile -t kola_args < <(get_kola_args "${instance_type}") + + kola_tests=( "${@}" ) + kola_run "${tapfile}" kola_args kola_tests + } + + # Skip the set -x set +e setup done by vendor_test.sh, we are + # doing a verbose call to kola ourselves. + local CIA_SKIP_KOLA_TESTS_SHELL_WRAPPER=x + run_kola_tests_on_instances \ + "${CNV_MAIN_INSTANCE}" \ + "${CIA_TAPFILE}" \ + "${CIA_FIRST_RUN}" \ + "${CNV_EXTRA_INSTANCES[@]}" \ + -- \ + "${CNV_EXTRA_INSTANCE_TESTS[@]}" \ + -- \ + "${CNVI_ALL_TESTS[@]}" + + unset -f run_kola_tests query_kola_tests +} + +function kola_run() { + local tapfile="${1}"; shift + local kola_args_var_name="${1}"; shift + local kola_tests_var_name="${1}"; shift + local -a common_opts kola_cmd + + local -n kola_args_var="${kola_args_var_name}" + local -n kola_tests_var="${kola_tests_var_name}" + + common_opts=( + --board="${CIA_ARCH}-usr" + --tapfile="${tapfile}" + --torcx-manifest="${CIA_TORCX_MANIFEST}" + --channel="${CIA_CHANNEL}" + ) + kola_cmd=() + if [[ -n "${CNV_TIMEOUT:-}" ]]; then + kola_cmd+=( timeout --signal=SIGQUIT "${CNV_TIMEOUT}" ) + fi + kola_cmd+=( + kola run + "${common_opts[@]}" + "${kola_args_var[@]}" + "${kola_tests_var[@]}" + ) + printf "%q" "${kola_cmd[@]}"; printf '\n' + "${kola_cmd[@]}" || : + if [[ ! -e "${tapfile}" ]]; then + generate_fail_tapfile "${tapfile}" "${kola_tests_var[@]}" + fi +} diff --git a/ci-automation/new_vendor_test.sh b/ci-automation/new_vendor_test.sh new file mode 100644 index 0000000000..5d83c62847 --- /dev/null +++ b/ci-automation/new_vendor_test.sh @@ -0,0 +1,243 @@ +#!/bin/bash +# Copyright (c) 2021 The Flatcar Maintainers. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -euo pipefail + +# Test execution script for the azure vendor image. +# This script is supposed to run in the mantle container. + +source ci-automation/vendor_test.sh + +function generate_broken_test_tapfile { + local error_msg="${1}"; shift + echo "1..1" > "${CIA_TAPFILE}" + echo "not ok - all ${CNV_PLATFORM:-(unknown platform, define CNV_PLATFORM!)} tests" >> "${CIA_TAPFILE}" + echo " ---" >> "${CIA_TAPFILE}" + echo " ERROR: ${error_msg}" | tee -a "${CIA_TAPFILE}" + echo " ..." >> "${CIA_TAPFILE}" +} + +function generate_broken_test_tapfile_and_die { + generate_broken_test_tapfile "${@}" + break_retest_cycle + exit 1 +} + +function generate_fail_tapfile() { + local tapfile="${1}"; shift + # rest of the args are test names + echo "1..${#@}" >"${tapfile}" + printf 'not ok - %s\n' "${@}" >>"${tapfile}" +} + +function check_vars { + if ! declare -p "${@}" >/dev/null 2>&1; then + return 1 + fi + return 0 +} + +function check_funcs { + if ! declare -pF "${@}" >/dev/null 2>&1; then + return 1 + fi + return 0 +} + +CNVI_PHASE='pre-run' +CNVI_ALL_TESTS=( "${@}" ) + +function handle_setup_failures() { + local error_msg + case "${CNVI_PHASE}" in + pre-run) + error_msg='Something failed before running the setup' + ;; + setup) + error_msg='Setup failed' + ;; + *) + return 0; + ;; + esac + # We didn't even reach kola invocation. Let's create a tapfile + # with all the tests marked as a failure. This can be done only if + # the query_kola_tests function and some output variables were + # defined, though. That means that vendor tests should define them + # as early as possible. + if ! check_vars CNV_PLATFORM CNV_MAIN_INSTANCE CNV_EXTRA_INSTANCES CNV_EXTRA_INSTANCE_TESTS; then + echo "handle_setup_failures: '${CIA_TESTSCRIPT}' did not define all the required variables to handle the setup failure" + return 0 + fi + + local -a instance_tests + local -a all_tests + local other_tests_for_fgrep + local instance + + function query_kola_tests { + shift + kola list --platform="${CNV_PLATFORM}" --filter "${@}" + } + + instance_tests=() + all_tests=() + if [[ "${CIA_FIRST_RUN}" -eq 1 ]]; then + # The "-t" option strips the delimiter. "mapfile" clears the + # instance_tests array before assigning to it. + mapfile -t instance_tests < <(run_query_kola_tests "${CNV_MAIN_INSTANCE}" "${CNVI_ALL_TESTS[@]}") + all_tests+=( "${instance_tests[@]}" ) + + other_tests_for_fgrep="$(printf '%s\n' "${CNVI_EXTRA_INSTANCE_TESTS[@]}")" + for instance in "${CNVI_EXTRA_INSTANCES[@]}"; do + mapfile -t instance_tests < <(run_query_kola_tests "${instance}" "${CNVI_ALL_TESTS[@]}" | grep --only-matching --fixed-strings "${other_tests_for_fgrep}" || :) + all_tests+=( "${instance_tests[@]/#/extra_test.[${instance}].}" ) + done + else + all_tests=( "${CNVI_ALL_TESTS[@]}" ) + fi + + unset -f query_kola_tests + + generate_fail_tapfile "${CIA_TAPFILE}" "${all_tests[@]}" + return 0 +} +trap handle_setup_failures ERR + +function ensure_arch { + local arch + for arch; do + if [[ "${CIA_ARCH}" == "${arch}" ]]; then + return 0 + fi + done + generate_broken_test_tapfile_and_die "${CIA_ARCH} tests not supported on ${CNV_PLATFORM}" +} + +function ensure_tests { + local kola_test + for kola_test in "${CNVI_ALL_TESTS[@]}"; do + if [[ "${kola_test}" = '*' ]]; then + CNVI_ALL_TESTS=( "${@}" ) + return 0 + fi + done + local sup_kola_test ok + for kola_test in "${CNVI_ALL_TESTS[@]}"; do + ok= + for sup_kola_test; do + if [[ "${kola_test}" = "${sup_kola_test}" ]] || [[ "${kola_test}" = 'extra-test.['*"].${sup_kola_test}" ]]; then + ok=x + break + fi + if [[ -z "${ok}" ]]; then + generate_broken_test_tapfile_and_die "'${kola_test}' test case is not supported in ${CIA_TESTSCRIPT}" + fi + done + done + return 0 +} + +function run_default_kola_tests { + local variables=( + CNV_MAIN_INSTANCE + CNV_EXTRA_INSTANCES + CNV_EXTRA_INSTANCE_TESTS + CNV_PLATFORM + ) + local funcs=( + get_kola_args + failible_setup + ) + local f + + if ! check_vars "${variables[@]}"; then + generate_broken_test_tapfile_and_die "At least one of ${variables[@]} variables is not defined." + fi + if ! check_funcs "${funcs[@]}"; then + generate_broken_test_tapfile_and_die "At least one of ${funcs[@]} functions is not defined." + fi + for f in query_kola_tests run_kola_tests; do + if check_funcs "${f}"; then + generate_broken_test_tapfile_and_die "Function ${f} can't be defined, it will be clobbered by us." + fi + done + + if [[ -n "${CNV_SUPPORTED_TESTS[@]:-}" ]]; then + ensure_tests "${CNV_SUPPORTED_TESTS[@]}" + fi + + if [[ -n "${CNV_SUPPORTED_ARCH[@]:-}" ]]; then + ensure_arch "${CNV_SUPPORTED_ARCH[@]}" + fi + + CNVI_PHASE='setup' + failible_setup + CNVI_PHASE='run' + + function query_kola_tests { + shift + kola list --platform="${CNV_PLATFORM}" --filter "${@}" + } + + function run_kola_tests { + local instance_type="${1}"; shift + local instance_tapfile="${1}"; shift + local -a kola_args kola_tests + + mapfile -t kola_args < <(get_kola_args "${instance_type}") + + kola_tests=( "${@}" ) + kola_run "${tapfile}" kola_args kola_tests + } + + # Skip the set -x set +e setup done by vendor_test.sh, we are + # doing a verbose call to kola ourselves. + local CIA_SKIP_KOLA_TESTS_SHELL_WRAPPER=x + run_kola_tests_on_instances \ + "${CNV_MAIN_INSTANCE}" \ + "${CIA_TAPFILE}" \ + "${CIA_FIRST_RUN}" \ + "${CNV_EXTRA_INSTANCES[@]}" \ + -- \ + "${CNV_EXTRA_INSTANCE_TESTS[@]}" \ + -- \ + "${CNVI_ALL_TESTS[@]}" + + unset -f run_kola_tests query_kola_tests +} + +function kola_run() { + local tapfile="${1}"; shift + local kola_args_var_name="${1}"; shift + local kola_tests_var_name="${1}"; shift + local -a common_opts kola_cmd + + local -n kola_args_var="${kola_args_var_name}" + local -n kola_tests_var="${kola_tests_var_name}" + + common_opts=( + --board="${CIA_ARCH}-usr" + --tapfile="${tapfile}" + --torcx-manifest="${CIA_TORCX_MANIFEST}" + --channel="${CIA_CHANNEL}" + --platform="${CNV_PLATFORM}" + ) + kola_cmd=() + if [[ -n "${CNV_TIMEOUT:-}" ]]; then + kola_cmd+=( timeout --signal=SIGQUIT "${CNV_TIMEOUT}" ) + fi + kola_cmd+=( + kola run + "${common_opts[@]}" + "${kola_args_var[@]}" + "${kola_tests_var[@]}" + ) + printf "%q" "${kola_cmd[@]}"; printf '\n' + "${kola_cmd[@]}" || : + if [[ ! -e "${tapfile}" ]]; then + generate_fail_tapfile "${tapfile}" "${kola_tests_var[@]}" + fi +} diff --git a/ci-automation/vendor-testing/aws.sh b/ci-automation/vendor-testing/aws.sh index 505c60ecb2..31ae14a233 100755 --- a/ci-automation/vendor-testing/aws.sh +++ b/ci-automation/vendor-testing/aws.sh @@ -8,59 +8,59 @@ set -euo pipefail # Test execution script for the AWS vendor image. # This script is supposed to run in the mantle container. -source ci-automation/vendor_test.sh +source ci-automation/new_vendor_test.sh -board="${CIA_ARCH}-usr" -escaped_vernum="${CIA_VERNUM//+/-}" -image_name="ci-${escaped_vernum}-${CIA_ARCH}" -aws_instance_type_var="AWS_${CIA_ARCH}_INSTANCE_TYPE" -aws_instance_type="${!aws_instance_type_var}" -more_aws_instance_types_var="AWS_${CIA_ARCH}_MORE_INSTANCE_TYPES" -mapfile -t more_aws_instance_types < <(tr ' ' '\n' <<<"${!more_aws_instance_types_var}") +cvt_board="${CIA_ARCH}-usr" +cvt_escaped_vernum="${CIA_VERNUM//+/-}" +cvt_image_name="ci-${cvt_escaped_vernum}-${CIA_ARCH}" +cvt_aws_instance_type_var="AWS_${CIA_ARCH}_INSTANCE_TYPE" +cvt_aws_instance_type="${!cvt_aws_instance_type_var}" +cvt_more_aws_instance_types_var="AWS_${CIA_ARCH}_MORE_INSTANCE_TYPES" +mapfile -t cvt_more_aws_instance_types < <(tr ' ' '\n' <<<"${!cvt_more_aws_instance_types_var}") -CIA_OUTPUT_MAIN_INSTANCE="${aws_instance_type}" -CIA_OUTPUT_ALL_TESTS=( "${@}" ) -CIA_OUTPUT_EXTRA_INSTANCES=( "${more_aws_instance_types[@]}" ) -CIA_OUTPUT_EXTRA_INSTANCE_TESTS=( 'cl.internet' ) -CIA_OUTPUT_TIMEOUT=6h +CNV_MAIN_INSTANCE="${cvt_aws_instance_type}" +CNV_EXTRA_INSTANCES=( "${cvt_more_aws_instance_types[@]}" ) +CNV_EXTRA_INSTANCE_TESTS=( 'cl.internet' ) +CNV_PLATFORM=aws +CNV_TIMEOUT=6h -query_kola_tests() { - shift; # ignore the instance type - kola list --platform=aws --filter "${@}" +function failible_setup { + local image_file='flatcar_production_ami_image.bin' + local tarball="${image_file}.bz2" + local aws_bucket + local aws_s3_path + + if [[ "${AWS_AMI_ID}" == "" ]]; then + if [[ -f "${image_file}" ]]; then + echo "++++ ${CIA_TESTSCRIPT}: using existing ${image_file} for ${CIA_VERNUM} (${CIA_ARCH}) ++++" + else + echo "++++ ${CIA_TESTSCRIPT}: downloading ${tarball} for ${CIA_VERNUM} (${CIA_ARCH}) ++++" + copy_from_buildcache "images/${CIA_ARCH}/${CIA_VERNUM}/${tarball}" . + lbunzip2 "${tarball}" + fi + + aws_bucket="flatcar-kola-ami-import-${AWS_REGION}" + aws_s3_path="s3://${aws_bucket}/${cvt_escaped_vernum}/${cvt_board}/" + trap 'ore -d aws delete --region="${AWS_REGION}" --board="${cvt_board}" --name="${cvt_image_name}" --ami-name="${cvt_image_name}" --file="${image_file}" --bucket "${aws_s3_path}"' EXIT + ore aws initialize --region="${AWS_REGION}" --bucket "${aws_bucket}" + AWS_AMI_ID=$(ore aws upload --force --region="${AWS_REGION}" --board="${cvt_board}" --name="${cvt_image_name}" --ami-name="${cvt_image_name}" --ami-description="Flatcar Test ${cvt_image_name}" --file="${image_file}" --object-format=RAW --force --bucket "${aws_s3_path}" | jq -r .HVM) + echo "++++ ${CIA_TESTSCRIPT}: created new AMI ${AWS_AMI_ID} (will be removed after testing) ++++" + fi } -image_file='flatcar_production_ami_image.bin' -tarball="${image_file}.bz2" - -if [[ "${AWS_AMI_ID}" == "" ]]; then - if [[ -f "${image_file}" ]]; then - echo "++++ ${CIA_TESTSCRIPT}: using existing ${image_file} for ${CIA_VERNUM} (${CIA_ARCH}) ++++" - else - echo "++++ ${CIA_TESTSCRIPT}: downloading ${tarball} for ${CIA_VERNUM} (${CIA_ARCH}) ++++" - copy_from_buildcache "images/${CIA_ARCH}/${CIA_VERNUM}/${tarball}" . - lbunzip2 "${tarball}" - fi - - aws_bucket="flatcar-kola-ami-import-${AWS_REGION}" - aws_s3_path="s3://${aws_bucket}/${escaped_vernum}/${board}/" - trap 'ore -d aws delete --region="${AWS_REGION}" --board="${board}" --name="${image_name}" --ami-name="${image_name}" --file="${image_file}" --bucket "${aws_s3_path}"' EXIT - ore aws initialize --region="${AWS_REGION}" --bucket "${aws_bucket}" - AWS_AMI_ID=$(ore aws upload --force --region="${AWS_REGION}" --board="${board}" --name="${image_name}" --ami-name="${image_name}" --ami-description="Flatcar Test ${image_name}" --file="${image_file}" --object-format=RAW --force --bucket "${aws_s3_path}" | jq -r .HVM) - echo "++++ ${CIA_TESTSCRIPT}: created new AMI ${AWS_AMI_ID} (will be removed after testing) ++++" -fi - -run_kola_tests() { +function get_kola_args { local instance_type="${1}"; shift - kola_run \ - --basename="${image_name}" \ + local args=( + --basename="${cvt_image_name}" \ --offering='basic' \ --parallel="${AWS_PARALLEL}" \ - --platform=aws \ --aws-ami="${AWS_AMI_ID}" \ --aws-region="${AWS_REGION}" \ --aws-type="${instance_type}" \ --aws-iam-profile="${AWS_IAM_PROFILE}" + ) + printf '%s\n' "${args[@]}" } # these are set in ci-config.env diff --git a/ci-automation/vendor-testing/azure.sh b/ci-automation/vendor-testing/azure.sh index 57aaf6ce15..0c4c895852 100755 --- a/ci-automation/vendor-testing/azure.sh +++ b/ci-automation/vendor-testing/azure.sh @@ -8,78 +8,72 @@ set -euo pipefail # Test execution script for the azure vendor image. # This script is supposed to run in the mantle container. -source ci-automation/vendor_test.sh +source ci-automation/new_vendor_test.sh -# $@ now contains tests / test patterns to run - -basename="ci-${CIA_VERNUM//+/-}-${CIA_ARCH}" -azure_instance_type_var="AZURE_${CIA_ARCH}_MACHINE_SIZE" -azure_instance_type="${!azure_instance_type_var}" -azure_extra_options=() -other_instance_types=() +cvt_basename="ci-${CIA_VERNUM//+/-}-${CIA_ARCH}" +cvt_azure_instance_type_var="AZURE_${CIA_ARCH}_MACHINE_SIZE" +cvt_azure_instance_type="${!cvt_azure_instance_type_var}" +cvt_azure_extra_options=() +cvt_other_instance_types=() if [[ -n "${AZURE_USE_PRIVATE_IPS:-}" ]]; then - azure_extra_options+=( --azure-use-private-ips ) + cvt_azure_extra_options+=( --azure-use-private-ips ) fi if [[ "${CIA_ARCH}" == "arm64" ]] || [[ -n "${AZURE_USE_GALLERY:-}" ]]; then - azure_extra_options+=( '--azure-use-gallery' ) + cvt_azure_extra_options+=( '--azure-use-gallery' ) fi if [[ -n "${AZURE_VNET_SUBNET_NAME:-}" ]]; then - azure_extra_options+=( --azure-vnet-subnet-name="${AZURE_VNET_SUBNET_NAME}" ) + cvt_azure_extra_options+=( --azure-vnet-subnet-name="${AZURE_VNET_SUBNET_NAME}" ) fi if [[ "${CIA_ARCH}" = 'amd64' ]]; then - other_instance_types+=('V1') + cvt_other_instance_types+=('V1') fi -CIA_OUTPUT_MAIN_INSTANCE="${azure_instance_type}" -CIA_OUTPUT_ALL_TESTS=( "${@}" ) -CIA_OUTPUT_EXTRA_INSTANCES=( "${other_instance_types[@]}" ) -CIA_OUTPUT_EXTRA_INSTANCE_TESTS=( 'cl.internet' ) +CNV_MAIN_INSTANCE="${cvt_azure_instance_type}" +CNV_EXTRA_INSTANCES=( "${cvt_other_instance_types[@]}" ) +CNV_EXTRA_INSTANCE_TESTS=( 'cl.internet' ) +CNV_PLATFORM=azure # Align timeout with ore azure gc --duration parameter -CIA_OUTPUT_TIMEOUT=6h +CNV_TIMEOUT=6h -query_kola_tests() { - shift; # ignore the instance type - kola list --platform=azure --filter "${@}" +failible_setup() { + cvt_azure_profile_config_file='' + secret_to_file cvt_azure_profile_config_file "${AZURE_PROFILE}" + cvt_azure_auth_config_file='' + secret_to_file cvt_azure_auth_config_file "${AZURE_AUTH_CREDENTIALS}" + + # Fetch the Azure image if not present + if [ -f "${AZURE_IMAGE_NAME}" ] ; then + echo "++++ ${CIA_TESTSCRIPT}: Using existing ${AZURE_IMAGE_NAME} for testing ${CIA_VERNUM} (${CIA_ARCH}) ++++" + else + echo "++++ ${CIA_TESTSCRIPT}: downloading ${AZURE_IMAGE_NAME} for ${CIA_VERNUM} (${CIA_ARCH}) ++++" + copy_from_buildcache "images/${CIA_ARCH}/${CIA_VERNUM}/${AZURE_IMAGE_NAME}.bz2" . + cp --sparse=always <(lbzcat "${AZURE_IMAGE_NAME}.bz2") "${AZURE_IMAGE_NAME}" + rm "${AZURE_IMAGE_NAME}.bz2" + fi } -azure_profile_config_file='' -secret_to_file azure_profile_config_file "${AZURE_PROFILE}" -azure_auth_config_file='' -secret_to_file azure_auth_config_file "${AZURE_AUTH_CREDENTIALS}" - -# Fetch the Azure image if not present -if [ -f "${AZURE_IMAGE_NAME}" ] ; then - echo "++++ ${CIA_TESTSCRIPT}: Using existing ${AZURE_IMAGE_NAME} for testing ${CIA_VERNUM} (${CIA_ARCH}) ++++" -else - echo "++++ ${CIA_TESTSCRIPT}: downloading ${AZURE_IMAGE_NAME} for ${CIA_VERNUM} (${CIA_ARCH}) ++++" - copy_from_buildcache "images/${CIA_ARCH}/${CIA_VERNUM}/${AZURE_IMAGE_NAME}.bz2" . - cp --sparse=always <(lbzcat "${AZURE_IMAGE_NAME}.bz2") "${AZURE_IMAGE_NAME}" - rm "${AZURE_IMAGE_NAME}.bz2" -fi - - -run_kola_tests() { +get_kola_args() { local instance_type="${1}"; shift local hyperv_gen="V2" if [ "${instance_type}" = "V1" ]; then hyperv_gen="V1" - instance_type="${azure_instance_type}" + instance_type="${cvt_azure_instance_type}" fi - kola_run \ - --basename="${basename}" \ - --parallel="${AZURE_PARALLEL}" \ - --offering=basic \ - --platform=azure \ - --azure-image-file="${AZURE_IMAGE_NAME}" \ - --azure-location="${AZURE_LOCATION}" \ - --azure-profile="${azure_profile_config_file}" \ - --azure-auth="${azure_auth_config_file}" \ - --azure-size="${instance_type}" \ - --azure-hyper-v-generation="${hyperv_gen}" \ - "${azure_extra_options[@]}" \ - "${@}" + local args=( + --basename="${cvt_basename}" + --parallel="${AZURE_PARALLEL}" + --offering=basic + --azure-image-file="${AZURE_IMAGE_NAME}" + --azure-location="${AZURE_LOCATION}" + --azure-profile="${cvt_azure_profile_config_file}" + --azure-auth="${cvt_azure_auth_config_file}" + --azure-size="${instance_type}" + --azure-hyper-v-generation="${hyperv_gen}" + "${cvt_azure_extra_options[@]}" + ) + printf '%s\n' "${args}" } run_default_kola_tests diff --git a/ci-automation/vendor-testing/test.sh b/ci-automation/vendor-testing/test.sh index 5cd3a39b78..f7b8f1c00c 100755 --- a/ci-automation/vendor-testing/test.sh +++ b/ci-automation/vendor-testing/test.sh @@ -8,47 +8,44 @@ set -euo pipefail # Test execution script for the test non-vendor non-image. # This script is supposed to run in the mantle container. -source ci-automation/vendor_test.sh +source ci-automation/new_vendor_test.sh -# $@ now contains tests / test patterns to run +CNV_MAIN_INSTANCE='default' +CNV_EXTRA_INSTANCES=( 'extra1' 'extra2' ) +CNV_EXTRA_INSTANCE_TESTS=( 'cl.internet' ) +CNV_PLATFORM=test +CNV_TIMEOUT=10s -CIA_OUTPUT_MAIN_INSTANCE='default' -CIA_OUTPUT_ALL_TESTS=( "${@}" ) -CIA_OUTPUT_EXTRA_INSTANCES=( 'extra1' 'extra2' ) -CIA_OUTPUT_EXTRA_INSTANCE_TESTS=( 'cl.internet' ) -CIA_OUTPUT_TIMEOUT=10s +function failible_test { + if [[ ! -d path-override ]]; then + mkdir path-override + fi + if [[ ! -e 'path-override/kola' ]]; then + cp "${CIA_VENDOR_SCRIPTS_DIR}/test-kola.sh" 'path-override/kola' + fi + if [[ ! -x 'path-override/kola' ]]; then + chmod a+x 'path-override/kola' + fi + export PATH="${PWD}/path-override:${PATH}" -query_kola_tests() { - shift; # ignore the instance type - kola list --platform=test --filter "${@}" + for test_name; do + case "${test_name}" in + 'fail.setup') + echo 'failing setup' + false + ;; + esac + done } -if [[ ! -d path-override ]]; then - mkdir path-override -fi -if [[ ! -e 'path-override/kola' ]]; then - cp "${CIA_VENDOR_SCRIPTS_DIR}/test-kola.sh" 'path-override/kola' -fi -if [[ ! -x 'path-override/kola' ]]; then - chmod a+x 'path-override/kola' -fi -export PATH="${PWD}/path-override:${PATH}" - -for test_name; do - case "${test_name}" in - 'fail.setup') - echo 'failing setup' - false - ;; - esac -done - -run_kola_tests() { +get_kola_args() { local instance_type="${1}"; shift - - kola_run \ - --parallel=42 \ + local -a args + args=( + --parallel=42 --platform=test + ) + printf '%s\n' "${args[@]}" } run_default_kola_tests diff --git a/ci-automation/vendor_test.sh b/ci-automation/vendor_test.sh index 10bbd90e39..74f9969585 100644 --- a/ci-automation/vendor_test.sh +++ b/ci-automation/vendor_test.sh @@ -117,61 +117,6 @@ CIA_VENDOR_SCRIPTS_DIR="${ciavts_vendor_scripts_dir}" # Unset all variables with ciavts_ prefix now. unset -v "${!ciavts_@}" -function generate_fail_tapfile() { - local tapfile="${1}"; shift - # rest of the args are test names - echo "1..${#@}" >"${tapfile}" - printf 'not ok - %s\n' "${@}" >>"${tapfile}" -} - -trap handle_flaky_setup ERR -function handle_flaky_setup() { - if [[ -e "${CIA_TAPFILE}" ]]; then - # Tests had their run, tapfile was created, nothing to do - # here. - return 0 - fi - # Tapfile wasn't created, which means that we didn't even reach - # kola invocation. Let's create a tapfile with all the tests - # marked as a failure. This can be done only if the - # query_kola_tests function and some output variables were - # defined, though. That means that vendor tests should define them - # as early as possible. - if ! declare -p CIA_OUTPUT_MAIN_INSTANCE CIA_OUTPUT_ALL_TESTS CIA_OUTPUT_EXTRA_INSTANCES CIA_OUTPUT_EXTRA_INSTANCE_TESTS >/dev/null 2>&1; then - echo "handle_flaky_setup: '${CIA_TESTSCRIPT}' did not define all the required variables to handle the setup failure" - return 0 - fi - if [[ "$(type -t query_kola_tests || true)" != 'function' ]]; then - echo "handle_flaky_setup: '${CIA_TESTSCRIPT}' did not define the query_kola_tests function to handle the setup failure" - return 0 - fi - - local -a instance_tests - local -a all_tests - local other_tests_for_fgrep - local instance - - instance_tests=() - all_tests=() - if [[ "${CIA_FIRST_RUN}" -eq 1 ]]; then - # The "-t" option strips the delimiter. "mapfile" clears the - # instance_tests array before assigning to it. - mapfile -t instance_tests < <(run_query_kola_tests "${CIA_OUTPUT_MAIN_INSTANCE}" "${CIA_OUTPUT_ALL_TESTS[@]}") - all_tests+=( "${instance_tests[@]}" ) - - other_tests_for_fgrep="$(printf '%s\n' "${CIA_OUTPUT_EXTRA_INSTANCE_TESTS[@]}")" - for instance in "${CIA_OUTPUT_EXTRA_INSTANCES[@]}"; do - mapfile -t instance_tests < <(run_query_kola_tests "${instance}" "${CIA_OUTPUT_ALL_TESTS[@]}" | grep --only-matching --fixed-strings "${other_tests_for_fgrep}" || :) - all_tests+=( "${instance_tests[@]/#/extra_test.[${instance}].}" ) - done - else - all_tests=( "${CIA_OUTPUT_ALL_TESTS[@]}" ) - fi - - generate_fail_tapfile "${CIA_TAPFILE}" "${all_tests[@]}" - return 0 -} - # Prefixes all test names in the tap file with a given prefix, so the # test name like "cl.basic" will become "extra-test.[${prefix}].cl.basic". # @@ -312,6 +257,8 @@ function merge_tap_files() { # # run_kola_tests that takes the following parameters: # 1 - instance type +# 2 - tap file +# @ - tests to run # # query_kola_tests that takes the following parameters: # 1 - instance type @@ -321,26 +268,28 @@ function merge_tap_files() { # the line will be ignored. # # Typical use: -# -# CIA_OUTPUT_MAIN_INSTANCE=… -# CIA_OUTPUT_ALL_TESTS=( … ) -# CIA_OUTPUT_EXTRA_INSTANCES=( … ) -# CIA_OUTPUT_EXTRA_INSTANCE_TESTS=( … ) -# CIA_OUTPUT_TIMEOUT=… -# # function run_kola_tests() { # local instance_type="${1}"; shift -# kola_run … +# local tap_file="${1}"; shift +# kola run … "${@}" # } # -# # Setup (download and prepare images for kola) -# # function query_kola_tests() { # local instance_type="${1}"; shift # kola list … "${@}" # } # -# run_default_kola_tests +# args=( +# "${main_instance}" +# "${CIA_TAPFILE}" +# "${CIA_FIRST_RUN}" +# "${other_instance_types[@]}" +# '--' +# 'cl.internet' +# '--' +# "${tests_to_run[@]}" +# ) +# run_kola_tests_on_instances "${args[@]}" # # Parameters: # 1 - main instance type - there all the tests are being run @@ -427,13 +376,24 @@ function run_kola_tests_on_instances() { } # An internal function that invokes the user-defined run_kola_tests -# callback. It defines the CIA_INTERNAL_TAPFILE variable, which is -# used by the kola_run function. +# callback. It's normally done inside a subshell with set +e and set +# -x. CIA_SKIP_KOLA_TESTS_SHELL_WRAPPER can be used to run the +# callback directly, if the callback is doing something like this on +# its own. function run_kola_tests_internal() { local instance_type="${1}"; shift - local CIA_INTERNAL_TAPFILE="${1}"; shift - local CIA_INTERNAL_TESTS=( "${@}" ) - run_kola_tests "${instance_type}" "${@}" + local tapfile="${1}"; shift + if [[ -n "${CIA_SKIP_KOLA_TESTS_SHELL_WRAPPER:-}" ]]; then + run_kola_tests "${instance_type}" "${tapfile}" "${@}" + else + # run in a subshell, so the set -x and set +e do not pollute + # the outer environment + ( + set +e + set -x + run_kola_tests "${instance_type}" "${tapfile}" "${@}" + true + ) } # Runs the user-defined query_kola_tests callback and massages its @@ -443,69 +403,3 @@ function run_query_kola_tests() { # that follows it. query_kola_tests "${@}" | tail -n +3 | awk '{ print $1 }' } - -# Invokes run_kola_tests_on_instances with arguments from various CIA_ -# variables. Will only work if the vendor test specifies the necessary -# output variables. -function run_default_kola_tests() { - if ! declare -p CIA_OUTPUT_MAIN_INSTANCE CIA_OUTPUT_ALL_TESTS CIA_OUTPUT_EXTRA_INSTANCES CIA_OUTPUT_EXTRA_INSTANCE_TESTS >/dev/null 2>&1; then - echo "1..1" > "${CIA_TAPFILE}" - echo "not ok - all the tests for ${CIA_TESTSCRIPT}" >> "${CIA_TAPFILE}" - echo " ---" >> "${CIA_TAPFILE}" - echo " ERROR: ${CIA_TESTSCRIPT} tried to invoke run_default_kola_tests but didn't specify the necessary variables" | tee -a "${CIA_TAPFILE}" - echo " ..." >> "${CIA_TAPFILE}" - break_retest_cycle - return 1 - fi - run_kola_tests_on_instances \ - "${CIA_OUTPUT_MAIN_INSTANCE}" \ - "${CIA_TAPFILE}" \ - "${CIA_FIRST_RUN}" \ - "${CIA_OUTPUT_EXTRA_INSTANCES[@]}" \ - '--' \ - "${CIA_OUTPUT_EXTRA_INSTANCE_TESTS[@]}" \ - '--' \ - "${CIA_OUTPUT_ALL_TESTS[@]}" -} - -# Invokes kola. Does it with a timeout if CIA_OUTPUT_TIMEOUT is not -# empty. All the parameters passed to this function are forwarded to -# "kola run". There's no need to specify "--board", "--channel", -# "--torcx-manifest" and "--tapfile" parameters - this function will -# pass those based on the various CIA_ variables. Usable only inside -# run_kola_tests callback used by run_default_kola_tests or -# run_kola_tests_on_instances. -function kola_run() { - local -a common_opts kola_cmd - - common_opts=( - --board="${CIA_ARCH}-usr" - --tapfile="${CIA_INTERNAL_TAPFILE}" - --torcx-manifest="${CIA_TORCX_MANIFEST}" - --channel="${CIA_CHANNEL}" - ) - kola_cmd=() - if [[ -n "${CIA_OUTPUT_TIMEOUT:-}" ]]; then - kola_cmd+=( timeout --signal=SIGQUIT "${CIA_OUTPUT_TIMEOUT}" ) - fi - kola_cmd+=( kola run "${common_opts[@]}" "${@}" "${CIA_INTERNAL_TESTS[@]}" ) - # Run in a subshell to avoid executing the err handler. - ( - printf "%q" "${kola_cmd[@]}"; printf '\n' - "${kola_cmd[@]}" || : - ) - # In case of timeout, the tapfile might be still missing. But - # since we were ignoring the error at the time, handle_flaky_setup - # didn't run, so do it now. - if [[ ! -e "${CIA_INTERNAL_TAPFILE}" ]]; then - generate_fail_tapfile "${CIA_INTERNAL_TAPFILE}" "${CIA_INTERNAL_TESTS[@]}" - fi -} - -function unsafe_code_section() { - # Run in a subshell to avoid executing the err handler. - ( - echo "${@}" - "${@}" || : - ) -}