1#!/usr/bin/env bash
2# Copyright 2021 gRPC authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16set -eo pipefail
17
18# Constants
19readonly GITHUB_REPOSITORY_NAME="grpc"
20readonly TEST_DRIVER_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/${TEST_DRIVER_REPO_OWNER:-grpc}/grpc/${TEST_DRIVER_BRANCH:-master}/tools/internal_ci/linux/grpc_xds_k8s_install_test_driver.sh"
21## xDS test server/client Docker images
22readonly SERVER_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/python-server"
23readonly CLIENT_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/python-client"
24readonly FORCE_IMAGE_BUILD="${FORCE_IMAGE_BUILD:-0}"
25readonly BUILD_APP_PATH="interop-testing/build/install/grpc-interop-testing"
26readonly LANGUAGE_NAME="Python"
27
28#######################################
29# Builds test app Docker images and pushes them to GCR
30# Globals:
31#   BUILD_APP_PATH
32#   SERVER_IMAGE_NAME: Test server Docker image name
33#   CLIENT_IMAGE_NAME: Test client Docker image name
34#   GIT_COMMIT: SHA-1 of git commit being built
35#   TESTING_VERSION: version branch under test, f.e. v1.42.x, master
36# Arguments:
37#   None
38# Outputs:
39#   Writes the output of `gcloud builds submit` to stdout, stderr
40#######################################
41build_test_app_docker_images() {
42  echo "Building ${LANGUAGE_NAME} xDS interop test app Docker images"
43
44  pushd "${SRC_DIR}"
45  docker build \
46    -f src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.client \
47    -t "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \
48    .
49
50  docker build \
51    -f src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.server \
52    -t "${SERVER_IMAGE_NAME}:${GIT_COMMIT}" \
53    .
54
55  popd
56
57  gcloud -q auth configure-docker
58
59  docker push "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}"
60  docker push "${SERVER_IMAGE_NAME}:${GIT_COMMIT}"
61
62  if is_version_branch "${TESTING_VERSION}"; then
63    tag_and_push_docker_image "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" "${TESTING_VERSION}"
64    tag_and_push_docker_image "${SERVER_IMAGE_NAME}" "${GIT_COMMIT}" "${TESTING_VERSION}"
65  fi
66}
67
68#######################################
69# Builds test app and its docker images unless they already exist
70# Globals:
71#   SERVER_IMAGE_NAME: Test server Docker image name
72#   CLIENT_IMAGE_NAME: Test client Docker image name
73#   GIT_COMMIT: SHA-1 of git commit being built
74#   FORCE_IMAGE_BUILD
75# Arguments:
76#   None
77# Outputs:
78#   Writes the output to stdout, stderr
79#######################################
80build_docker_images_if_needed() {
81  # Check if images already exist
82  server_tags="$(gcloud_gcr_list_image_tags "${SERVER_IMAGE_NAME}" "${GIT_COMMIT}")"
83  printf "Server image: %s:%s\n" "${SERVER_IMAGE_NAME}" "${GIT_COMMIT}"
84  echo "${server_tags:-Server image not found}"
85
86  client_tags="$(gcloud_gcr_list_image_tags "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}")"
87  printf "Client image: %s:%s\n" "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}"
88  echo "${client_tags:-Client image not found}"
89
90  # Build if any of the images are missing, or FORCE_IMAGE_BUILD=1
91  if [[ "${FORCE_IMAGE_BUILD}" == "1" || -z "${server_tags}" || -z "${client_tags}" ]]; then
92    build_test_app_docker_images
93  else
94    echo "Skipping ${LANGUAGE_NAME} test app build"
95  fi
96}
97
98#######################################
99# Executes the test case
100# Globals:
101#   TEST_DRIVER_FLAGFILE: Relative path to test driver flagfile
102#   KUBE_CONTEXT: The name of kubectl context with GKE cluster access
103#   TEST_XML_OUTPUT_DIR: Output directory for the test xUnit XML report
104#   SERVER_IMAGE_NAME: Test server Docker image name
105#   CLIENT_IMAGE_NAME: Test client Docker image name
106#   GIT_COMMIT: SHA-1 of git commit being built
107#   TESTING_VERSION: version branch under test: used by the framework to determine the supported PSM
108#                    features.
109# Arguments:
110#   Test case name
111# Outputs:
112#   Writes the output of test execution to stdout, stderr
113#   Test xUnit report to ${TEST_XML_OUTPUT_DIR}/${test_name}/sponge_log.xml
114#######################################
115run_test() {
116  # Test driver usage:
117  # https://github.com/grpc/grpc/tree/master/tools/run_tests/xds_k8s_test_driver#basic-usage
118  local test_name="${1:?Usage: run_test test_name}"
119  local out_dir="${TEST_XML_OUTPUT_DIR}/${test_name}"
120  mkdir -pv "${out_dir}"
121  set -x
122  python3 -m "tests.${test_name}" \
123    --flagfile="${TEST_DRIVER_FLAGFILE}" \
124    --kube_context="${KUBE_CONTEXT}" \
125    --server_image="${SERVER_IMAGE_NAME}:${GIT_COMMIT}" \
126    --client_image="${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \
127    --testing_version="${TESTING_VERSION}" \
128    --nocheck_local_certs \
129    --force_cleanup \
130    --collect_app_logs \
131    --log_dir="${out_dir}" \
132    --xml_output_file="${out_dir}/sponge_log.xml" \
133    |& tee "${out_dir}/sponge_log.log"
134  set +x
135}
136
137#######################################
138# Main function: provision software necessary to execute tests, and run them
139# Globals:
140#   KOKORO_ARTIFACTS_DIR
141#   GITHUB_REPOSITORY_NAME
142#   SRC_DIR: Populated with absolute path to the source repo
143#   TEST_DRIVER_REPO_DIR: Populated with the path to the repo containing
144#                         the test driver
145#   TEST_DRIVER_FULL_DIR: Populated with the path to the test driver source code
146#   TEST_DRIVER_FLAGFILE: Populated with relative path to test driver flagfile
147#   TEST_XML_OUTPUT_DIR: Populated with the path to test xUnit XML report
148#   GIT_ORIGIN_URL: Populated with the origin URL of git repo used for the build
149#   GIT_COMMIT: Populated with the SHA-1 of git commit being built
150#   GIT_COMMIT_SHORT: Populated with the short SHA-1 of git commit being built
151#   KUBE_CONTEXT: Populated with name of kubectl context with GKE cluster access
152# Arguments:
153#   None
154# Outputs:
155#   Writes the output of test execution to stdout, stderr
156#######################################
157main() {
158  local script_dir
159  script_dir="$(dirname "$0")"
160
161  # Source the test driver from the master branch.
162  echo "Sourcing test driver install script from: ${TEST_DRIVER_INSTALL_SCRIPT_URL}"
163  source /dev/stdin <<< "$(curl -s "${TEST_DRIVER_INSTALL_SCRIPT_URL}")"
164
165  activate_gke_cluster GKE_CLUSTER_PSM_SECURITY
166
167  set -x
168  if [[ -n "${KOKORO_ARTIFACTS_DIR}" ]]; then
169    kokoro_setup_test_driver "${GITHUB_REPOSITORY_NAME}"
170  else
171    local_setup_test_driver "${script_dir}"
172  fi
173  build_docker_images_if_needed
174  # Run tests
175  cd "${TEST_DRIVER_FULL_DIR}"
176  local failed_tests=0
177  test_suites=("baseline_test" "security_test" "authz_test")
178  for test in "${test_suites[@]}"; do
179    run_test $test || (( ++failed_tests ))
180  done
181  echo "Failed test suites: ${failed_tests}"
182}
183
184main "$@"
185