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