/
githubmirror
/
kubernetes
Обзор
Документация
Войти
/
githubmirror
/
kubernetes
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
hack/verify-e2e-test-ownership.sh
212 строк
7 KB
Benjamin Elder
declare and assign seperately in hack/verify-e2e-test-ownership.sh
20 окт 2022, 09:46
20 окт 2022, 09:46
103e6cd
Код
Авторство
О чём код?
#!/usr/bin/env bash # Copyright 2014 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This script verifies the following e2e test ownership policies # - tests MUST start with [sig-foo] # - tests SHOULD NOT have multiple [sig-foo] tags # TODO: these two can be dropped if KubeDescribe is gone from codebase # - tests MUST NOT have [k8s.io] in test names # - tests MUST NOT use KubeDescribe set -o errexit set -o nounset set -o pipefail # This will canonicalize the path KUBE_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd -P) source "${KUBE_ROOT}/hack/lib/init.sh" # Set REUSE_BUILD_OUTPUT=y to skip rebuilding dependencies if present REUSE_BUILD_OUTPUT=${REUSE_BUILD_OUTPUT:-n} # set VERBOSE_OUTPUT=y to output .jq files and shell commands VERBOSE_OUTPUT=${VERBOSE_OUTPUT:-n} if [[ ${VERBOSE_OUTPUT} =~ ^[yY]$ ]]; then set -x fi pushd "${KUBE_ROOT}" > /dev/null # Setup a tmpdir to hold generated scripts and results tmpdir=$(mktemp -d -t verify-e2e-test-ownership.XXXX) readonly tmpdir trap 'rm -rf ${tmpdir}' EXIT # input spec_summaries="${KUBE_ROOT}/_output/specsummaries.json" # output results_json="${tmpdir}/results.json" summary_json="${tmpdir}/summary.json" failures_json="${tmpdir}/failures.json" # rebuild dependencies if necessary function ensure_dependencies() { local -r ginkgo="${KUBE_ROOT}/_output/bin/ginkgo" local -r e2e_test="${KUBE_ROOT}/_output/bin/e2e.test" if ! { [ -f "${ginkgo}" ] && [[ "${REUSE_BUILD_OUTPUT}" =~ ^[yY]$ ]]; }; then make ginkgo fi if ! { [ -f "${e2e_test}" ] && [[ "${REUSE_BUILD_OUTPUT}" =~ ^[yY]$ ]]; }; then hack/make-rules/build.sh test/e2e/e2e.test fi if ! { [ -f "${spec_summaries}" ] && [[ "${REUSE_BUILD_OUTPUT}" =~ ^[yY]$ ]]; }; then "${ginkgo}" --dry-run=true "${e2e_test}" -- --spec-dump "${spec_summaries}" > /dev/null fi } # evaluate ginkgo spec summaries against e2e test ownership polices # output to ${results_json} function generate_results_json() { readonly results_jq=${tmpdir}/results.jq cat >"${results_jq}" <<EOS [.[] | select( .LeafNodeType == "It") | . as { ContainerHierarchyTexts: \$text, ContainerHierarchyLocations: \$code, LeafNodeText: \$leafText, LeafNodeLocation: \$leafCode} | { calls: ([ \$text | range(0;length) as \$i | { sig: ((\$text[\$i] | match("\\\[(sig-[^\\\]]+)\\\]") | .captures[0].string) // "unknown"), text: \$text[\$i], # unused, but if we ever wanted to have policies based on other tags... # tags: \$text[\$i] | [match("(\\\[[^\\\]]+\\\])"; "g").string], line: \$code[\$i] | "\(.FileName):\(.LineNumber)" }] + [{ sig: ((\$leafText | match("\\\[(sig-[^\\\]]+)\\\]") | .captures[0].string) // "unknown"), text: \$leafText, # unused, but if we ever wanted to have policies based on other tags... # tags: \$leafText | [match("(\\\[[^\\\]]+\\\])"; "g").string], line: \$leafCode | "\(.FileName):\(.LineNumber)" }]), } | { owner: .calls[0].sig, calls: .calls, testname: .calls | map(.text) | join(" "), policies: [( .calls[0] | { fail: (.sig == "unknown"), level: "FAIL", category: "unowned_test", reason: "must start with [sig-foo]", found: ., } ), ( .calls[1:] | (map(select(.sig != "unknown")) // [] | { fail: . | any, level: "WARN", category: "too_many_sigs", reason: "should not have multiple [sig-foo] tags", found: ., }) ) ] }] EOS if [[ ${VERBOSE_OUTPUT} =~ ^[yY]$ ]]; then echo "about to ${results_jq}..." cat -n "${results_jq}" echo fi <"${spec_summaries}" jq --slurp --from-file "${results_jq}" > "${results_json}" } # summarize e2e test policy results # output to ${summary_json} function generate_summary_json() { summary_jq=${tmpdir}/summary.jq cat >"${summary_jq}" <<EOS . as \$results | # for each policy category reduce \$results[0].policies[] as \$p ({}; . + { # add a convenience .policy field containing that policy's result (\$p.category): \$results | map(. + {policy: .policies[] | select(.category == \$p.category)}) | { level: \$p.level, reason: \$p.reason, passing: map(select(.policy.fail | not)) | length, failing: map(select(.policy.fail)) | length, testnames: map(select(.policy.fail) | .testname), } }) # add a meta policy based on whether any policy failed + { all_policies: \$results | { level: "WARN", reason: "should pass all policies", passing: map(select(.policies | map(.fail) | any | not)) | length, failing: map(select(.policies | map(.fail) | any)) | length, testnames: map(select(.policies | map(.fail) | any) | .testname), } } # if a policy has no failing tests, change its log output to PASS | with_entries(.value += { log: (if (.value.failing == 0) then "PASS" else .value.level end) }) # sort by policies with the most failing tests first | to_entries | sort_by(.value.failing) | reverse | from_entries EOS if [[ ${VERBOSE_OUTPUT} =~ ^[yY]$ ]]; then echo "about to run ${results_jq}..." cat -n "${summary_jq}" echo fi <"${results_json}" jq --from-file "${summary_jq}" > "${summary_json}" } # filter e2e policy tests results to tests that failed, with the policies they failed # output to ${failures_json} function generate_failures_json() { local -r failures_jq="${tmpdir}/failures.jq" cat >"${failures_jq}" <<EOS . # for each test | map( # filter down to failing policies; trim category, .reason is more verbose .policies |= map(select(.fail) | del(.category)) # trim the full callstack, .found will contain the relevant call | del(.calls) ) # filter down to tests that have failed policies | map(select(.policies | map (.fail) | any)) EOS if [[ ${VERBOSE_OUTPUT} =~ ^[yY]$ ]]; then echo "about to run ${failures_jq}..." cat -n "${failures_jq}" echo fi <"${results_json}" jq --from-file "${failures_jq}" > "${failures_json}" } function output_results_and_exit_if_failed() { local -r total_tests=$(<"${spec_summaries}" wc -l | awk '{print $1}') # output results to console ( echo "run at datetime: $(date -u +%Y-%m-%dT%H:%M:%SZ)" echo "based on commit: $(git log -n1 --date=iso-strict --pretty='%h - %cd - %s')" echo <"${failures_json}" cat printf "%4s: e2e tests %-40s: %-4d\n" "INFO" "in total" "${total_tests}" <"${summary_json}" jq -r 'to_entries[].value | "printf \"%4s: ..failing %-40s: %-4d\\n\" \"\(.log)\" \"\(.reason)\" \"\(.failing)\""' | sh ) | tee "${tmpdir}/output.txt" # if we said "FAIL" in that output, we should fail if <"${tmpdir}/output.txt" grep -q "^FAIL"; then echo "FAIL" exit 1 fi } ensure_dependencies generate_results_json generate_failures_json generate_summary_json output_results_and_exit_if_failed echo "PASS"