#! /bin/bash # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You 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. #-------------------------------------------------------------------- # Utility script for running the new integration tests, since the Maven # commands are unwieldy. Allows straightforward usage of ITs on the desktop # and in various build scripts. Handles configuration of various kinds. set -e # Enable for debugging #set -x export DRUID_DEV=$(cd $(dirname $0) && pwd) function usage { cat < [] Start the cluster for category. down [] Stop the cluster for category. run [] Run the tests for the given module on an alread-running cluster. Does not stop the cluster. Primarily for debugging. test [] Start the cluster, run the test for category, and stop the cluster. tail [] Show the last 20 lines of each container log. gen [] Generate docker-compose.yaml files (done automatically on up) run one IT in Travis (build dist, image, run test, tail logs). github [] Run one IT in Github Workflows (run test, tail logs). prune-containers Stop all running Docker containers. Do this if "down" won't work because the "docker-compose.yaml" file is no longer available. prune-volumes prune Docker volumes. Arguments: category: A defined IT JUnit category, and IT- profile module: relative path to the module with tests. Defaults to integration-tests-ex/cases Environment: OVERRIDE_ENV: optional, name of env file to pass to Docker USE_INDEXER: Set to middleManager (default if not set) or "indexer". If "indexer", requires docker-compose-indexer.yaml exist. druid_*: passed to the container. Other, test-specific variables. See docs for additional details. EOF } function tail_logs { pushd $MODULE_DIR/target/$CATEGORY/logs > /dev/null ls *.log | while read log; do echo "----- $CATEGORY/$log -----" tail -100 $log done popd > /dev/null } # Many tests require us to pass information into containers using environment variables. # The Docker environment is distinct from the environment running this script. We bridge # the two by passing into Docker compose a file that contains all env vars we want to # "export" from our local environment into the container environment. # There are three ways to provide these options: # # 1. Directly in the environment. (Simplest and best.) We support a fixed set of variables: # # 2. For ad-hoc use, as var=value pairs in a file with the same name as the # test catagory, in the home folder under ~/druid-it. Example: # BatchIndex.env. Use this to hold credentials and other info which you must # pass into tests when running locally. # 3. A file given by the OVERRIDE_ENV environment variable. That is, OVERRIDE_ENV holds # the path to a file of var=value pairs. Historically, this file was created by a # build environment such as Github Actions. However, it is actually simpler just to use # option 1: just set the values in the environment and let Linux pass them through to # this script. # 4. Environment variables of the form "druid_" used to create the Druid config file. # # All of the above are combined into a temporary environment file which is then passed # into Docker compose. # # The file is built when the cluster comes up. It is reused in the test and down # commands so we have a consistent environment. function build_override { mkdir -p "$MODULE_DIR/target" OVERRIDE_FILE="$MODULE_DIR/target/override.env" rm -f "$OVERRIDE_FILE" touch "$OVERRIDE_FILE" # Provided override file if [ -n "$OVERRIDE_ENV" ]; then if [ ! -f "$OVERRIDE_ENV" ]; then echo "Environment override file OVERRIDE_ENV not found: $OVERRIDE_ENV" 1>&2 exit 1 fi cat "$OVERRIDE_ENV" >> "$OVERRIDE_FILE" fi # User-local settings? LOCAL_ENV="$HOME/druid-it/${CATEGORY}.env" if [ -f "$LOCAL_ENV" ]; then cat "$LOCAL_ENV" >> "$OVERRIDE_FILE" fi # Add all environment variables of the form druid_* set +e # Grep gives exit status 1 if no lines match. Let's not fail. env | grep "^druid_" >> "$OVERRIDE_FILE" set -e # TODO: Add individual env vars that we want to pass from the local # environment into the container. # Reuse the OVERRIDE_ENV variable to pass the full list to Docker compose export OVERRIDE_ENV="$OVERRIDE_FILE" } function reuse_override { OVERRIDE_FILE="$MODULE_DIR/target/override.env" if [ ! -f "$OVERRIDE_FILE" ]; then echo "Override file $OVERRIDE_FILE not found: Was an 'up' run?" 1>&2 exit 1 fi export OVERRIDE_ENV="$OVERRIDE_FILE" } function require_category { if [ -z "$CATEGORY" ]; then usage 1>&2 exit 1 fi } function require_env_var { if [ -z "$1" ]; then echo "$1 must be set for test category $CATEGORY" 1>&2 exit 1 fi } # Verfiy any test-specific environment variables that must be set in this local # environment (and generally passed into the Docker container via docker-compose.yaml). # # Add entries here as you add env var references in docker-compose.yaml. Doing so # ensures we get useful error messages when we forget to set something, rather than # some cryptic use-specific error. function verify_env_vars { VERIFY_SCRIPT="$MODULE_DIR/cluster/$DRUID_INTEGRATION_TEST_GROUP/verify.sh" if [ -f "$VERIFY_SCRIPT" ]; then . "$VERIFY_SCRIPT" fi } if [ $# -eq 0 ]; then usage exit 1 fi CMD=$1 shift if [ $# -gt 0 ]; then CATEGORY=$1 shift fi # Handle an IT in either the usual druid-it-cases project, or elsewhere, # typically in an extension. The Maven module, if needed must be the third # parameter in path, not coordinate, form. if [ $# -eq 0 ]; then # Use the usual project MAVEN_PROJECT=":druid-it-cases" # Don't provide a project path to cluster.sh unset IT_MODULE_DIR # Generate the override.sh file in the druid-it-cases module MODULE_DIR=$DRUID_DEV/integration-tests-ex/cases else # The test module is given via the command line argument as a relative path MAVEN_PROJECT="$1" # Compute the full path to the target module for use by cluster.sh export IT_MODULE_DIR="$DRUID_DEV/$1" # Write the override.sh file to the target module MODULE_DIR=$IT_MODULE_DIR shift fi IT_CASES_DIR="$DRUID_DEV/integration-tests-ex/cases" # Added -Dcyclonedx.skip=true to avoid ISO-8859-1 [ERROR]s # May be fixed in the future MAVEN_IGNORE="-P skip-static-checks,skip-tests -Dmaven.javadoc.skip=true -Dcyclonedx.skip=true" TEST_OPTIONS="verify -P skip-static-checks,docker-tests \ -Dmaven.javadoc.skip=true -Dcyclonedx.skip=true -DskipUTs=true" case $CMD in "help" ) usage ;; "ci" ) mvn -q clean install dependency:go-offline -P dist $MAVEN_IGNORE ;; "build" ) mvn -B clean install -P dist $MAVEN_IGNORE -T1.0C $* ;; "dist" ) mvn -B install -P dist $MAVEN_IGNORE -pl :distribution ;; "tools" ) mvn -B install -pl :druid-it-tools ;; "image" ) cd $DRUID_DEV/integration-tests-ex/image mvn -B install -P test-image $MAVEN_IGNORE ;; "gen") # Generate the docker-compose.yaml files. Mostly for debugging # since the up command does generation implicitly. require_category $IT_CASES_DIR/cluster.sh gen $CATEGORY ;; "up" ) require_category build_override verify_env_vars $IT_CASES_DIR/cluster.sh up $CATEGORY ;; "down" ) require_category reuse_override $IT_CASES_DIR/cluster.sh down $CATEGORY ;; "run" ) require_category reuse_override mvn -B $TEST_OPTIONS -P IT-$CATEGORY -pl $MAVEN_PROJECT ;; "test" ) require_category build_override verify_env_vars $IT_CASES_DIR/cluster.sh up $CATEGORY # Run the test. On failure, still shut down the cluster. # Return Maven's return code as the script's return code. set +e mvn -B $TEST_OPTIONS -P IT-$CATEGORY -pl $MAVEN_PROJECT RESULT=$? set -e $IT_CASES_DIR/cluster.sh down $CATEGORY exit $RESULT ;; "tail" ) require_category tail_logs ;; "github" ) set +e $0 test $CATEGORY RESULT=$? # Include logs, but only for failures. if [ $RESULT -ne 0 ]; then $0 tail $CATEGORY fi exit $RESULT ;; # Name is deliberately long to avoid accidental use. "prune-containers" ) if [ $(docker ps | wc -l) -ne 1 ]; then echo "Cleaning running containers" docker ps docker ps -aq | xargs -r docker rm -f fi ;; "prune-volumes" ) # Caution: this removes all volumes, which is generally what you # want when testing. docker system prune -af --volumes ;; * ) usage exit 1 ;; esac