#!/bin/bash # Test case for Weldr API (on-premise) distro dot notation and aliases. # # This test case verifies that distributions can be specified with and without # the dot to sepratae the major and minor version (true for RHEL-8 and RHEL-9). # It also verifies the behavior of distro name aliases # (e.g. "rhel-9" -> "rhel-9.5"). This is done by building a SAP image and # inspecting it using guestfish. Specifically, the SAP image contains DNF VAR # config /etc/dnf/vars/releasever, which contains value "X.Y", which should be # the same as the distro release that the alias points to. set -xeuo pipefail source /usr/libexec/osbuild-composer-test/set-env-variables.sh source /usr/libexec/tests/osbuild-composer/shared_lib.sh # Don't run in nightly pipeline until we have the version with dot-notation in nightly compose if ! nvrGreaterOrEqual "osbuild-composer" "100"; then echo "osbuild-composer version is too old, skipping the test" exit 0 fi TMPDIR=$(mktemp -d) greenprint "Registering clean ups" function cleanup() { greenprint "== Script execution stopped or finished - Cleaning up ==" set +eu rm -rf "${TMPDIR}" set -eu } trap cleanup EXIT # Remove any restrictions on the image types for weldr API, since # testing the distro alias requires building the SAP image. # # Also override the alias for RHEL 8 since the default alias, 8.10, doesn't # have a locked version, so the releasever is not set in the dnf vars, and this # test relies on that file to verify that we are using the correct distro # object and code path. EXTRA_COMPOSER_CONF="$(mktemp -p "$TMPDIR")" cat < " exit 1 fi local blueprint="$1" local blueprint_name="$2" sudo composer-cli blueprints push "${blueprint}" sudo composer-cli blueprints depsolve "${blueprint_name}" sudo composer-cli blueprints delete "${blueprint_name}" } # Common test case for verifying that the provided blueprint can produce an image. function _test_compose_bp() { if [[ $# -lt 3 || $# -gt 5 ]]; then echo "Usage: _test_compose_bp [] []" exit 1 fi local blueprint="$1" local blueprint_name="$2" local tmpdir="$3" local image_type="${4:-qcow2}" local test_distro_alias="${5:-0}" local composestart="${tmpdir}/compose-start.json" local composeinfo="${tmpdir}/compose-info.json" sudo composer-cli blueprints push "${blueprint}" sudo composer-cli --json compose start "${blueprint_name}" "${image_type}" | tee "${composestart}" local composeid composeid=$(get_build_info '.build_id' "${composestart}") # Wait for the compose to finish. local composestatus echo "⏱ Waiting for compose to finish: ${composeid}" while true; do sudo composer-cli --json compose info "${composeid}" | tee "${composeinfo}" > /dev/null composestatus=$(get_build_info '.queue_status' "${composeinfo}") # Is the compose finished? if [[ ${composestatus} != RUNNING ]] && [[ ${composestatus} != WAITING ]]; then break fi # Wait 30 seconds and try again. sleep 30 done jq . "${composeinfo}" # Did the compose finish with success? if [[ $composestatus != FINISHED ]]; then echo "Something went wrong with the compose. 😢" exit 1 fi if [[ "${test_distro_alias}" == "1" ]]; then pushd "${tmpdir}" _verify_distro_alias_img "${composeid}" popd fi sudo composer-cli compose delete "${composeid}" >/dev/null } # Verify that the image contains /etc/dnf/vars/releasever with the expected # content. Specifically, verify that the content of /etc/dnf/vars/releasever # is the same as the VERSION_ID of the distro that the distro alias point to. function _verify_distro_alias_img() { if [[ $# -ne 1 ]]; then echo "Usage: _verify_distro_alias_img " exit 1 fi local compose_id="$1" local image_file image_file=$(sudo composer-cli compose image "${compose_id}") if [[ ! -f "${image_file}" ]]; then echo "Image file ${image_file} does not exist." exit 1 fi # uncompress the file if compressed if [[ "${image_file}" == *.xz ]]; then sudo unxz "${image_file}" image_file="${image_file%.xz}" fi local dnf_vars_releasever="/etc/dnf/vars/releasever" greenprint "Check ${dnf_vars_releasever} in the image" local dnf_vars_releasever_content dnf_vars_releasever_content=$(LIBGUESTFS_BACKEND=direct sudo --preserve-env=LIBGUESTFS_BACKEND guestfish --ro -a "${image_file}" -i cat "${dnf_vars_releasever}") if [[ "${dnf_vars_releasever_content}" != "${VERSION_ID}" ]]; then echo "Unexpected content of ${dnf_vars_releasever}: ${dnf_vars_releasever_content}" echo "Expected: ${VERSION_ID}" exit 1 fi } # Create a testing blueprint with wget package. function _create_blueprint() { if [[ $# -lt 2 ]] || [[ $# -gt 3 ]]; then echo "Usage: _create_blueprint []" exit 1 fi local directory="$1" local blueprint_name="$2" local distro="${3:-}" cat < "${directory}/${blueprint_name}.toml" name = "${blueprint_name}" description = "A testing blueprint" version = "0.0.1" EOF if [[ -n "${distro}" ]]; then cat <> "${directory}/${blueprint_name}.toml" distro = "${distro}" EOF fi cat <> "${directory}/${blueprint_name}.toml" [[packages]] name = "wget" EOF echo "${directory}/${blueprint_name}.toml" } # Common test case for repo configurations. function _test_repo() { local test_name="$1" local distro="$2" greenprint "TEST: ${test_name}" local directory="${TMPDIR}/${test_name}" mkdir -p "${directory}" stop_osbuild_composer clean_repo_dirs sudo cp "${DISTRO_TEST_REPO}" "${REPO_SHIPPED_DIR}/${distro}.json" start_osbuild_composer_clean local test_bp test_bp=$(_create_blueprint "${directory}" "${test_name}") _test_depsolving_bp "${test_bp}" "${test_name}" } # Test that the repository definitions can contain a dot in its filename, # separating the major and minor version. function test_repo_with_dot() { _test_repo "repo_with_dot" "${DISTRO}" } # Test that the repository definitions can be used without a dot in its filename, # even though the distro version may contain a dot. function test_repo_without_dot() { _test_repo "repo_without_dot" "${DISTRO_WITHOUT_DOT}" } # Test that the repository definitions with and without a dot in its filename # are equivalent and can override each other. Test uses empty file in the # shipped directory and the test repository in the overrides directory to # verify that the override happens. function test_repo_dot_overrides() { local test_name="repo_dot_overrides" greenprint "TEST: ${test_name}" local directory="${TMPDIR}/${test_name}" mkdir -p "${directory}" # Case 1: repo without dot in shipped dir, repo with dot in overrides dir stop_osbuild_composer clean_repo_dirs echo "{}" | sudo tee "${REPO_SHIPPED_DIR}/${DISTRO_WITHOUT_DOT}.json" sudo cp "${DISTRO_TEST_REPO}" "${REPO_OVERRIDES_DIR}/${DISTRO}.json" start_osbuild_composer_clean local test_bp test_bp=$(_create_blueprint "${directory}" "${test_name}") _test_depsolving_bp "${test_bp}" "${test_name}" # Case 2: repo with dot in shipped dir, repo without dot in overrides dir stop_osbuild_composer clean_repo_dirs echo "{}" | sudo tee "${REPO_SHIPPED_DIR}/${DISTRO}.json" sudo cp "${DISTRO_TEST_REPO}" "${REPO_OVERRIDES_DIR}/${DISTRO_WITHOUT_DOT}.json" start_osbuild_composer_clean test_bp=$(_create_blueprint "${directory}" "${test_name}") _test_depsolving_bp "${test_bp}" "${test_name}" } # Common test case for distro names in BP. function _test_distro() { local test_name="$1" local distro="$2" greenprint "TEST: ${test_name}" local directory="${TMPDIR}/${test_name}" mkdir -p "${directory}" stop_osbuild_composer clean_repo_dirs sudo cp "${DISTRO_TEST_REPO}" "${REPO_SHIPPED_DIR}" start_osbuild_composer_clean local test_bp test_bp=$(_create_blueprint "${directory}" "${test_name}" "${distro}") _test_depsolving_bp "${test_bp}" "${test_name}" _test_compose_bp "${test_bp}" "${test_name}" "${directory}" } # Test that the distro name in the blueprint can contain a dot in its name. function test_distro_with_dot() { _test_distro "distro_with_dot" "${DISTRO}" } # Test that the distro name in the blueprint can be used without a dot in its name. function test_distro_without_dot() { _test_distro "distro_without_dot" "${DISTRO_WITHOUT_DOT}" } # Test that the distro alias without the minor version can be used in the blueprint. # This test case requires that the test case is run on RHEL version which is # set as the target distro without minor version in the default composer configuration. function test_distro_alias() { local test_name="distro_alias" greenprint "TEST: ${test_name}" if [[ "${ID}" != "rhel" ]]; then echo "Testing distro alias requires RHEL distro." exit 1 fi local directory="${TMPDIR}/${test_name}" mkdir -p "${directory}" stop_osbuild_composer clean_repo_dirs sudo cp "${DISTRO_TEST_REPO}" "${REPO_SHIPPED_DIR}/${DISTRO_WITHOUT_MINOR}.json" start_osbuild_composer_clean local test_bp test_bp=$(_create_blueprint "${directory}" "${test_name}" "${DISTRO_WITHOUT_MINOR}") _test_depsolving_bp "${test_bp}" "${test_name}" _test_compose_bp "${test_bp}" "${test_name}" "${directory}" "ec2-sap" "1" } # Skip all tests if the DISTRO does not contain a dot. if [[ "${DISTRO}" == "${DISTRO_WITHOUT_DOT}" ]]; then echo "The distro does not contain dot to separate major and minor version." echo "Skipping the test, since testing the dot notation or aliases does not make sense." exit 0 fi # Run the tests. test_repo_with_dot test_repo_without_dot test_repo_dot_overrides test_distro_with_dot test_distro_without_dot test_distro_alias # If we got here, all tests passed. echo "All tests passed! 🥳" exit 0