#! /usr/bin/env bash # # Zeekctl test setup script. This script should be sourced in each test # script. This script requires that some env. vars. are correctly defined # in btest.cfg. # # This script installs Zeek to a directory that is unique to each test, # and provides a few functions and environment variables that can be used # directly by test scripts. # # This script provides these functions that can be used directly in # test scripts: # installfile Install a file into the test-specific Zeek install dir. # replaceprefix Replace text "@PREFIX@" in a specified file with the # test-specific directory path of the Zeek install. # # This script automatically exports some environment variables that are needed # by test scripts: # ZEEKCTL_INSTALL_PREFIX - Test-specific directory path of the Zeek install. # ZEEKCTL_INSTALL_PYTHON_DIR - Absolute path of the Python module directory # for the above install. # PATH - Enable test scripts to run the correct copy of "zeekctl" without # specifying a path. # # A user can modify the behavior of this script by setting any of the # following env. variables: # ZEEKCTL_TEST_DEBUG - If this is set (value doesn't matter), then the # test-specific Zeek install directory will not be removed # when a test terminates (this is useful for debugging). # installfile [] [--new] # # Install a file to the test-specific Zeek installation directory. # # The is the pathname (relative to the "Cfg" directory, which is # located in the btest base directory) of the file to be installed, # and it must follow a naming convention: /__ # where is the directory, is the destination filename, and # is some descriptive text for the file (to allow choosing # among different variations of the same file). # The file will be copied to $ZEEKCTL_INSTALL_PREFIX// # # If is specified, then the file will be copied to # $ZEEKCTL_INSTALL_PREFIX// # # The destination directory and file must already exist. # If "--new" is given, then skip check for existence of destination file. installfile() { set +x if [ -z "$1" ]; then return fi newfile="no" destdir="" origrelpath=$1 if [ -n "$2" ]; then if [ "$2" = "--new" ]; then newfile="yes" else destdir=$2 fi if [ "$3" = "--new" ]; then newfile="yes" fi fi # Make sure original file exists origpath=$ZEEKCTLCFG/$origrelpath if [ ! -f "$origpath" ]; then echo "Error: source file not found: $origpath" 1>&2 exit 1 fi # Remove the optional double-underscore delimiter (and following text) to # derive the destination filename relpath=$(echo $origrelpath | awk -F'__' '{print $1}') destfile=$(basename "$relpath") # Destination directory is either specified by user or is the original # directory path if [ -z "$destdir" ]; then destdir=$(dirname "$relpath") fi # If destination directory is not yet absolute, make it so: if [[ "$destdir" != /* ]]; then destdir="$ZEEKCTL_INSTALL_PREFIX/$destdir" fi # Make sure destination directory exists if [ ! -d "$destdir" ]; then echo "Error: destination directory not found: $destdir" 1>&2 exit 1 fi # Finally, build the destination pathname destpath=$destdir/$destfile if [ "$newfile" = "no" ]; then # Make sure destination file exists (usually, we're overwriting an # existing file, so this is a good safety check to catch typos) if [ ! -f "$destpath" ]; then echo "Error: destination file not found: $destpath (if this is a new file, use the --new option)" 1>&2 exit 1 fi fi cp $origpath $destpath set -x } # replaceprefix # # Replace the text "@PREFIX@" with the zeek install prefix in the specified # file (given as a relative pathname). replaceprefix() { set +x if [ -z "$1" ]; then return fi destfile=$ZEEKCTL_INSTALL_PREFIX/$1 if [ ! -f $destfile ]; then echo "Error: file not found: $destfile" 1>&2 exit 1 fi # Using "cp" and "rm" here in order to preserve permissions of file sed "s#@PREFIX@#${ZEEKCTL_INSTALL_PREFIX}#g" $destfile > $destfile.new && cp $destfile.new $destfile && rm $destfile.new test $? -ne 0 && exit 1 set -x } ##### # The following functions are needed by this script, but are not likely to be # needed by any zeekctl test scripts. # Normalize the specified pathname by resolving any ".." and symlinks in # the path. canonicalpath() { newpath=`python3 -c "from __future__ import print_function; import os,sys; print(os.path.realpath(sys.argv[1]))" "$1"` test $? -ne 0 && exit 1 echo $newpath } # Set the correct install prefix directory in all files where it's needed # (this is done immediately after untarring the Zeek install). replaceprefixes() { # Put in place the test's actual prefix in files where we # previously put in place the @PREFIX@ pattern: for i in etc/zeekctl.cfg bin/zeekctl bin/zeek-config ; do sed "s#@PREFIX@#${ZEEKCTL_INSTALL_PREFIX}#" $i > $i.new && cp $i.new $i && rm $i.new if [ $? -ne 0 ]; then return 1 fi done # We can now use zeek-config to figure out additional paths. This # avoids assumptions about where Zeek places directories. local pydir=$(./bin/zeek-config --python_dir) # Finally, substitute those in additional files whose location we # didn't previously know. for i in $pydir/zeekctl/ZeekControl/version.py ; do sed "s#@PREFIX@#${ZEEKCTL_INSTALL_PREFIX}#" $i > $i.new && cp $i.new $i && rm $i.new if [ $? -ne 0 ]; then return 1 fi done } # Cleanup when a zeekctl test script terminates for any reason (this is called # automatically). cleanup() { set +x set +e # Make sure all Zeek instances started by this test are stopped. # Hide the output to avoid user confusion if a test fails (for example, # this command will fail if "zeekctl install" was not run). zeekctl stop > /dev/null 2>&1 # Cleanup the test-specific Zeek install directory only if ZEEKCTL_TEST_DEBUG # is not set. if [ -z "${ZEEKCTL_TEST_DEBUG}" ]; then test -n "$ZEEKCTL_INSTALL_PREFIX" && rm -rf "$ZEEKCTL_INSTALL_PREFIX" fi } # Create a test-specific directory, install Zeek to this directory, and export # the env. vars. ZEEKCTL_INSTALL_PREFIX and PATH which are both needed by # zeekctl test scripts. main() { # Exit if any command fails (this is useful to debug a failing zeekctl test # script). set -e if [ -z "${INSTALL}" ]; then echo "Error: the INSTALL env. variable is not defined (should be in btest.cfg)" 1>&2 exit 1 fi basedir="${INSTALL}" tarfile=$basedir/zeek-test-install.tar if [ ! -f "$tarfile" ]; then echo "Error: $tarfile doesn't exist (run the 'Scripts/build-zeek' script)" 1>&2 exit 1 fi trap "cleanup" EXIT # Export "ZEEKCTL_INSTALL_PREFIX" which is used in test scripts that need # the directory path of the Zeek install. export ZEEKCTL_INSTALL_PREFIX=`canonicalpath "$basedir/test.$$"` # Create test-specific zeek installation directory mkdir "$ZEEKCTL_INSTALL_PREFIX" # Install zeek (cd "$ZEEKCTL_INSTALL_PREFIX" && tar xf "$tarfile" && replaceprefixes) # Update PATH to ensure that test scripts are running the correct copy of # zeekctl. export PATH=$ZEEKCTL_INSTALL_PREFIX/bin:$PATH # Provide the Python module installation directory to the tests. # This avoids hardwiring assumptions about the location of that # directory into the tests. export ZEEKCTL_INSTALL_PYTHON_DIR=$(zeek-config --python_dir) # If the user set the env. var. ZEEKCTL_TEST_DEBUG, then leave a file in # the test directory to help setup the environment for running zeekctl # manually. if [ -n "${ZEEKCTL_TEST_DEBUG}" ]; then how2run=${ZEEKCTL_INSTALL_PREFIX}/how_to_run_zeekctl echo "# In order to run zeekctl in this directory, type '. ./how_to_run_zeekctl'" >> $how2run echo "export PATH=$ZEEKCTL_INSTALL_PREFIX/bin:\$PATH" >> $how2run fi # Output all commands in a zeekctl test script (if a test fails, this might # be useful for debugging). set -x } main