github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/tests/main.sh (about)

     1  #!/bin/bash -e
     2  [ -n "${GOPATH:-}" ] && export "PATH=${PATH}:${GOPATH}/bin"
     3  
     4  # Always ignore SC2230 ('which' is non-standard. Use builtin 'command -v' instead.)
     5  export SHELLCHECK_OPTS="-e SC2230 -e SC2039 -e SC2028 -e SC2002 -e SC2005 -e SC2001 -e SC2263"
     6  export BOOTSTRAP_REUSE_LOCAL="${BOOTSTRAP_REUSE_LOCAL:-}"
     7  export BOOTSTRAP_REUSE="${BOOTSTRAP_REUSE:-false}"
     8  export BOOTSTRAP_PROVIDER="${BOOTSTRAP_PROVIDER:-lxd}"
     9  export BOOTSTRAP_CLOUD="${BOOTSTRAP_CLOUD:-lxd}"
    10  export BOOTSTRAP_SERIES="${BOOTSTRAP_SERIES:-}"
    11  export BOOTSTRAP_ARCH="${BOOTSTRAP_ARCH:-}"
    12  export BUILD_ARCH="${BUILD_ARCH:-}"
    13  export MODEL_ARCH="${MODEL_ARCH:-}"
    14  export BUILD_AGENT="${BUILD_AGENT:-false}"
    15  export RUN_SUBTEST="${RUN_SUBTEST:-}"
    16  export CURRENT_LTS="jammy"
    17  
    18  current_pwd=$(pwd)
    19  export CURRENT_DIR="${current_pwd}"
    20  
    21  OPTIND=1
    22  VERBOSE=1
    23  RUN_ALL="false"
    24  SKIP_LIST=""
    25  RUN_LIST=""
    26  ARTIFACT_FILE=""
    27  OUTPUT_FILE=""
    28  
    29  import_subdir_files() {
    30  	test "$1"
    31  	local file
    32  	for file in "$1"/*.sh; do
    33  		# shellcheck disable=SC1090
    34  		. "$file"
    35  	done
    36  }
    37  
    38  import_subdir_files includes
    39  
    40  # If adding a test suite, then ensure to add it here to be picked up!
    41  # Please keep these in alphabetic order.
    42  TEST_NAMES="agents \
    43              appdata \
    44              backup \
    45              bootstrap \
    46              branches \
    47              caasadmission \
    48              charmhub \
    49              cli \
    50              constraints \
    51              controller \
    52              coslite \
    53              credential \
    54              ck \
    55              deploy \
    56              deploy_aks \
    57              deploy_caas \
    58              firewall \
    59              hooks \
    60              hooktools \
    61              kubeflow \
    62              machine \
    63              magma \
    64              manual \
    65              model \
    66              network \
    67              ovs_maas \
    68              refresh \
    69              relations \
    70              resources \
    71              secrets_iaas \
    72              secrets_k8s \
    73              sidecar \
    74              smoke \
    75              spaces_ec2 \
    76              static_analysis \
    77              storage \
    78              unit \
    79              upgrade \
    80              user"
    81  
    82  # Show test suites, can be used to test if a test suite is available or not.
    83  show_test_suites() {
    84  	output=""
    85  	for test in ${TEST_NAMES}; do
    86  		name=$(echo "${test}" | sed -E "s/^run_//g" | sed -E "s/_/ /g")
    87  		# shellcheck disable=SC2086
    88  		output="${output}\n${test}"
    89  	done
    90  	echo -e "${output}" | column -t -s "|"
    91  	exit 0
    92  }
    93  
    94  show_help() {
    95  	version=$(juju version)
    96  	echo ""
    97  	echo "$(red 'Juju test suite')"
    98  	echo "¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯"
    99  	# shellcheck disable=SC2016
   100  	echo 'Juju tests suite expects you to have a Juju available on your $PATH,'
   101  	echo "so that if a tests needs to bootstrap it can just use that one"
   102  	echo "directly."
   103  	echo ""
   104  	echo "Juju Version:"
   105  	echo "¯¯¯¯¯¯¯¯¯¯¯¯¯"
   106  	echo "Using juju version: $(green "${version}")"
   107  	echo ""
   108  	echo "Usage:"
   109  	echo "¯¯¯¯¯¯"
   110  	echo "Flags should appear $(red 'before') arguments."
   111  	echo ""
   112  	echo "cmd [-h] [-v] [-A] [-s test] [-a file] [-x file] [-r] [-l controller] [-p provider type <lxd|aws|google|azure|manual|microk8s|vsphere|maas>]"
   113  	echo ""
   114  	echo "    $(green './main.sh -h')        Display this help message"
   115  	echo "    $(green './main.sh -v')        Verbose and debug messages"
   116  	echo "    $(green './main.sh -A')        Run all the test suites"
   117  	echo "    $(green './main.sh -s')        Skip tests using a comma seperated list"
   118  	echo "    $(green './main.sh -a')        Create an artifact file"
   119  	echo "    $(green './main.sh -x')        Output file from streaming the output"
   120  	echo "    $(green './main.sh -r')        Reuse bootstrapped controller between testing suites"
   121  	echo "    $(green './main.sh -l')        Local bootstrapped controller name to reuse"
   122  	echo "    $(green './main.sh -p')        Bootstrap provider to use when bootstrapping <lxd|aws|google|azure|manual|k8s|openstack|vsphere|maas>"
   123  	echo "                                     vsphere assumes juju boston vsphere for image metadata generation"
   124  	echo "                                     openstack assumes providing image data directly is not required"
   125  	echo "    $(green './main.sh -c')        Cloud name to use when bootstrapping, must be one of provider types listed above"
   126  	echo "    $(green './main.sh -R')        Region to use with cloud"
   127  	echo "    $(green './main.sh -S')        Bootstrap series to use <default is host>, priority over -l"
   128  	echo ""
   129  	echo "Tests:"
   130  	echo "¯¯¯¯¯¯"
   131  	echo "Available tests:"
   132  	echo ""
   133  
   134  	# Let's use the TEST_NAMES to print out what's available
   135  	output=""
   136  	for test in ${TEST_NAMES}; do
   137  		name=$(echo "${test}" | sed -E "s/^run_//g" | sed -E "s/_/ /g")
   138  		# shellcheck disable=SC2086
   139  		output="${output}\n    $(green ${test})|Runs the ${name} tests"
   140  	done
   141  	echo -e "${output}" | column -t -s "|"
   142  
   143  	echo ""
   144  	echo "Examples:"
   145  	echo "¯¯¯¯¯¯¯¯¯"
   146  	echo "Run a singular test:"
   147  	echo ""
   148  	echo "    $(green './main.sh static_analysis test_static_analysis_go')"
   149  	echo ""
   150  	echo "Run static analysis tests, but skip the go static analysis tests:"
   151  	echo ""
   152  	echo "    $(green './main.sh -s test_static_analysis_go static_analysis')"
   153  	echo ""
   154  	echo "Run a more verbose output and save that to an artifact tar (it"
   155  	echo "requires piping the output from stdout and stderr into a output.log,"
   156  	echo "which is then copied into the artifact tar file on test cleanup):"
   157  	echo ""
   158  	echo "    $(green './main.sh -v -a artifact.tar.gz -x output.log 2>&1|tee output.log')"
   159  	exit 1
   160  }
   161  
   162  while getopts "hH?vAs:a:x:rl:p:c:R:S:" opt; do
   163  	case "${opt}" in
   164  	h | \?)
   165  		show_help
   166  		;;
   167  	H)
   168  		show_test_suites
   169  		;;
   170  	v)
   171  		VERBOSE=2
   172  		# shellcheck disable=SC2262
   173  		alias juju="juju --debug"
   174  		;;
   175  	A)
   176  		RUN_ALL="true"
   177  		;;
   178  	s)
   179  		SKIP_LIST="${OPTARG}"
   180  		;;
   181  	a)
   182  		ARTIFACT_FILE="${OPTARG}"
   183  		;;
   184  	x)
   185  		OUTPUT_FILE="${OPTARG}"
   186  		;;
   187  	r)
   188  		export BOOTSTRAP_REUSE="true"
   189  		;;
   190  	l)
   191  		export BOOTSTRAP_REUSE_LOCAL="${OPTARG}"
   192  		export BOOTSTRAP_REUSE="true"
   193  
   194  		CLOUD=$(juju show-controller "${OPTARG}" --format=json 2>/dev/null | jq -r ".[\"${OPTARG}\"] | .details | .cloud")
   195  		PROVIDER=$(juju clouds --client --all --format=json 2>/dev/null | jq -r ".[\"${CLOUD}\"] | .type")
   196  		if [[ -z ${PROVIDER} ]]; then
   197  			PROVIDER="${CLOUD}"
   198  		fi
   199  		# We want "ec2" to redirect to "aws". This is needed e.g. for the ck tests
   200  		if [[ ${PROVIDER} == "ec2" ]]; then
   201  			PROVIDER="aws"
   202  		fi
   203  		export BOOTSTRAP_PROVIDER="${PROVIDER}"
   204  		export BOOTSTRAP_CLOUD="${CLOUD}"
   205  		;;
   206  	p)
   207  		export BOOTSTRAP_PROVIDER="${OPTARG}"
   208  		;;
   209  	c)
   210  		PROVIDER=$(juju clouds --client --all --format=json 2>/dev/null | jq -r ".[\"${OPTARG}\"] | .type")
   211  		export BOOTSTRAP_PROVIDER="${PROVIDER}"
   212  		CLOUD="${OPTARG}"
   213  		export BOOTSTRAP_CLOUD="${CLOUD}"
   214  		;;
   215  	R)
   216  		export BOOTSTRAP_REGION="${OPTARG}"
   217  		;;
   218  	S)
   219  		export BOOTSTRAP_SERIES="${OPTARG}"
   220  		;;
   221  	*)
   222  		echo "Unexpected argument ${opt}" >&2
   223  		exit 1
   224  		;;
   225  	esac
   226  done
   227  
   228  shift $((OPTIND - 1))
   229  [[ ${1:-} == "--" ]] && shift
   230  
   231  export VERBOSE="${VERBOSE}"
   232  export SKIP_LIST="${SKIP_LIST}"
   233  
   234  if [[ $# -eq 0 ]]; then
   235  	if [[ ${RUN_ALL} != "true" ]]; then
   236  		echo "$(red '---------------------------------------')"
   237  		echo "$(red 'Run with -A to run all the test suites.')"
   238  		echo "$(red '---------------------------------------')"
   239  		echo ""
   240  		show_help
   241  	fi
   242  fi
   243  
   244  echo ""
   245  
   246  echo "==> Checking for dependencies"
   247  check_dependencies curl jq yq shellcheck expect
   248  
   249  if [[ ${USER:-'root'} == "root" ]]; then
   250  	echo "The testsuite must not be run as root." >&2
   251  	exit 1
   252  fi
   253  
   254  JUJU_FOUND=0
   255  which juju &>/dev/null || JUJU_FOUND=$?
   256  if [[ $JUJU_FOUND == 0 ]]; then
   257  	echo "==> Using Juju located at $(which juju)"
   258  else
   259  	# shellcheck disable=SC2016
   260  	echo '==> WARNING: no Juju found on $PATH'
   261  fi
   262  
   263  cleanup() {
   264  	# Allow for failures and stop tracing everything
   265  	set +ex
   266  
   267  	# Allow for inspection
   268  	if [[ -n ${TEST_INSPECT:-} ]]; then
   269  		if [[ ${TEST_RESULT} != "success" ]]; then
   270  			echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}"
   271  		fi
   272  		echo "==> Test result: ${TEST_RESULT}"
   273  		echo "Tests Completed (${TEST_RESULT}): hit enter to continue"
   274  
   275  		# shellcheck disable=SC2034
   276  		read -r nothing
   277  	fi
   278  
   279  	echo "==> Cleaning up"
   280  
   281  	archive_logs "partial"
   282  
   283  	cleanup_pids
   284  	cleanup_jujus
   285  	cleanup_funcs
   286  
   287  	echo ""
   288  	if [[ ${TEST_RESULT} != "success" ]]; then
   289  		echo "==> TESTS DONE: ${TEST_CURRENT_DESCRIPTION}"
   290  		if [[ -f "${TEST_DIR}/${TEST_CURRENT}.log" ]]; then
   291  			echo "==> RUN OUTPUT: ${TEST_CURRENT}"
   292  			cat "${TEST_DIR}/${TEST_CURRENT}.log" | sed 's/^/    | /g'
   293  			echo ""
   294  		fi
   295  	fi
   296  	echo "==> Test result: ${TEST_RESULT}"
   297  
   298  	archive_logs "full"
   299  
   300  	if [ "${TEST_RESULT}" = "success" ]; then
   301  		rm -rf "${TEST_DIR}"
   302  		echo "==> Tests Removed: ${TEST_DIR}"
   303  	fi
   304  
   305  	echo "==> TEST COMPLETE"
   306  }
   307  
   308  # Move any artifacts to the chosen location
   309  archive_logs() {
   310  	if [[ -z ${ARTIFACT_FILE} ]]; then
   311  		return
   312  	fi
   313  
   314  	archive_type="${1}"
   315  
   316  	echo "==> Test ${archive_type} artifact: ${ARTIFACT_FILE}"
   317  	if [[ -f ${OUTPUT_FILE} ]]; then
   318  		cp "${OUTPUT_FILE}" "${TEST_DIR}"
   319  	fi
   320  	TAR_OUTPUT=$(tar -C "${TEST_DIR}" --transform s/./artifacts/ -zcvf "${ARTIFACT_FILE}" ./ 2>&1)
   321  	# shellcheck disable=SC2181
   322  	if [[ $? -eq 0 ]]; then
   323  		echo "==> Test ${archive_type} artifact: COMPLETED"
   324  	else
   325  		echo "${TAR_OUTPUT}"
   326  		TEST_RESULT=failure
   327  	fi
   328  
   329  }
   330  
   331  TEST_CURRENT=setup
   332  TEST_RESULT=failure
   333  
   334  trap cleanup EXIT HUP INT TERM
   335  
   336  # Setup test directory
   337  TEST_DIR=$(mktemp -d tmp.XXX | xargs -I % echo "$(pwd)/%")
   338  
   339  run_test() {
   340  	TEST_CURRENT=${1}
   341  	TEST_CURRENT_DESCRIPTION=${2:-${1}}
   342  	TEST_CURRENT_NAME=${TEST_CURRENT#"test_"}
   343  
   344  	if [[ -n ${4} ]]; then
   345  		TEST_CURRENT=${4}
   346  	fi
   347  
   348  	import_subdir_files "suites/${TEST_CURRENT_NAME}"
   349  
   350  	# shellcheck disable=SC2046,SC2086
   351  	echo "==> TEST BEGIN: ${TEST_CURRENT_DESCRIPTION} ($(green $(basename ${TEST_DIR})))"
   352  	START_TIME=$(date +%s)
   353  	${TEST_CURRENT}
   354  	END_TIME=$(date +%s)
   355  
   356  	echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION} ($((END_TIME - START_TIME))s)"
   357  }
   358  
   359  # allow for running a specific set of tests
   360  if [[ $# -gt 0 ]]; then
   361  	# shellcheck disable=SC2143
   362  	if [[ "$(echo "${2}" | grep -E "^run_")" ]]; then
   363  		TEST="$(grep -lr "run \"${2}\"" "suites/${1}" | xargs sed -rn 's/.*(test_\w+)\s+?\(\)\s+?\{/\1/p')"
   364  		if [[ -z ${TEST} ]]; then
   365  			echo "==> Unable to find parent test for ${2}."
   366  			echo "    Try and run the parent test directly."
   367  			exit 1
   368  		fi
   369  
   370  		export RUN_SUBTEST="${2}"
   371  		echo "==> Running subtest: ${2}"
   372  		run_test "test_${1}" "" "" "${TEST}"
   373  		TEST_RESULT=success
   374  		exit
   375  	fi
   376  	# shellcheck disable=SC2143
   377  	if [[ "$(echo "${2}" | grep -E "^test_")" ]]; then
   378  		TEST="$(grep -lr "${2}" "suites/${1}")"
   379  		if [[ -z ${TEST} ]]; then
   380  			echo "==> Unable to find test ${2} in ${1}."
   381  			echo "    Try and run the test suite directly."
   382  			exit 1
   383  		fi
   384  
   385  		export RUN_LIST="test_${1},${2}"
   386  		echo "==> Running subtest ${2} for ${1} suite"
   387  		run_test "test_${1}" "${1}" "" ""
   388  		TEST_RESULT=success
   389  		exit
   390  	fi
   391  
   392  	run_test "test_${1}" "" "$@" ""
   393  	TEST_RESULT=success
   394  	exit
   395  fi
   396  
   397  for test in ${TEST_NAMES}; do
   398  	name=$(echo "${test}" | sed -E "s/^run_//g" | sed -E "s/_/ /g")
   399  	run_test "test_${test}" "${name}" "" ""
   400  done
   401  
   402  TEST_RESULT=success