301 lines
12 KiB
Bash
301 lines
12 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Tell build process to exit if there are any errors.
|
|
set -euo pipefail
|
|
|
|
# Fail the build if dnf5 isn't installed
|
|
if ! rpm -q dnf5 &>/dev/null; then
|
|
echo "ERROR: Main dependency 'dnf5' is not installed. Install 'dnf5' before using this module to solve this error."
|
|
exit 1
|
|
fi
|
|
|
|
# Pull in repos
|
|
get_json_array REPOS 'try .["repos"][]' "${1}"
|
|
if [[ ${#REPOS[@]} -gt 0 ]]; then
|
|
echo "Adding repositories"
|
|
# Substitute %OS_VERSION% & remove newlines/whitespaces from all repo entries
|
|
for i in "${!REPOS[@]}"; do
|
|
repo="${REPOS[$i]}"
|
|
repo="${repo//%OS_VERSION%/${OS_VERSION}}"
|
|
REPOS[$i]="${repo//[$'\t\r\n ']}"
|
|
# Remove spaces/newlines for all repos other than COPR
|
|
if [[ "${repo}" != "COPR "* ]]; then
|
|
REPOS[$i]="${repo//[$'\t\r\n ']}"
|
|
else
|
|
REPOS[$i]="${repo}"
|
|
fi
|
|
done
|
|
# dnf config-manager & dnf copr don't support adding multiple repositories at once, hence why for/done loop is used
|
|
for repo in "${REPOS[@]}"; do
|
|
if [[ "${repo}" =~ ^https?:\/\/.* ]]; then
|
|
echo "Adding repository URL: '${repo}'"
|
|
dnf -y config-manager addrepo --from-repofile="${repo}"
|
|
elif [[ "${repo}" == *".repo" ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${repo}" ]]; then
|
|
echo "Adding repository file: '${repo##*/}'"
|
|
dnf -y config-manager addrepo --from-repofile="${CONFIG_DIRECTORY}/dnf/${repo}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
get_json_array COPR_REPOS 'try .["copr"][]' "${1}"
|
|
if [[ ${#COPR_REPOS[@]} -gt 0 ]]; then
|
|
echo "Adding COPR repos: ${COPR_REPOS[*]}"
|
|
for repo in "${COPR_REPOS[@]}"; do
|
|
echo "Adding COPR repository: '${repo}'"
|
|
dnf -y copr enable "${repo}"
|
|
done
|
|
fi
|
|
|
|
# Install RPM keys if they are provided
|
|
get_json_array KEYS 'try .["keys"][]' "${1}"
|
|
if [[ ${#KEYS[@]} -gt 0 ]]; then
|
|
echo "Adding keys"
|
|
for KEY in "${KEYS[@]}"; do
|
|
KEY="${KEY//%OS_VERSION%/${OS_VERSION}}"
|
|
rpm --import "${KEY//[$'\t\r\n ']}"
|
|
done
|
|
fi
|
|
|
|
# Create symlinks to fix packages that create directories in /opt
|
|
get_json_array OPTFIX 'try .["optfix"][]' "${1}"
|
|
if [[ ${#OPTFIX[@]} -gt 0 ]]; then
|
|
echo "Creating symlinks to fix packages that install to /opt"
|
|
# Create symlink for /opt to /var/opt since it is not created in the image yet
|
|
mkdir -p "/var/opt"
|
|
ln -snf "/var/opt" "/opt"
|
|
# Create symlinks for each directory specified in recipe.yml
|
|
for OPTPKG in "${OPTFIX[@]}"; do
|
|
OPTPKG="${OPTPKG%\"}"
|
|
OPTPKG="${OPTPKG#\"}"
|
|
mkdir -p "/usr/lib/opt/${OPTPKG}"
|
|
ln -s "../../usr/lib/opt/${OPTPKG}" "/var/opt/${OPTPKG}"
|
|
echo "Created symlinks for ${OPTPKG}"
|
|
done
|
|
fi
|
|
|
|
# Install & remove group packages
|
|
get_json_array GROUP_INSTALL 'try .["group-install"].["packages"][]' "${1}"
|
|
get_json_array GROUP_REMOVE 'try .["group-remove"].["packages"][]' "${1}"
|
|
|
|
# Get if 'install-weak-dependencies' is provided for group-install
|
|
WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["group-install"].["install-weak-dependencies"]')
|
|
|
|
if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then
|
|
WEAK_DEPS_FLAG="--setopt=install_weak_deps=True"
|
|
elif [[ "${WEAK_DEPENDENCIES}" == "false" ]]; then
|
|
WEAK_DEPS_FLAG="--setopt=install_weak_deps=False"
|
|
fi
|
|
|
|
# Get if 'skip-unavailable-packages' is provided for group-install
|
|
SKIP_UNAVAILABLE=$(echo "${1}" | jq -r 'try .["group-install"].["skip-unavailable-packages"]')
|
|
|
|
if [[ -z "${SKIP_UNAVAILABLE}" ]] || [[ "${SKIP_UNAVAILABLE}" == "null" ]] || [[ "${SKIP_UNAVAILABLE}" == "false" ]]; then
|
|
SKIP_UNAVAILABLE_FLAG=""
|
|
elif [[ "${SKIP_UNAVAILABLE}" == "true" ]]; then
|
|
SKIP_UNAVAILABLE_FLAG="--skip-unavailable"
|
|
fi
|
|
|
|
# Get if 'skip-broken-packages' is provided for group-install
|
|
SKIP_BROKEN=$(echo "${1}" | jq -r 'try .["group-install"].["skip-broken-packages"]')
|
|
|
|
if [[ -z "${SKIP_BROKEN}" ]] || [[ "${SKIP_BROKEN}" == "null" ]] || [[ "${SKIP_BROKEN}" == "false" ]]; then
|
|
SKIP_BROKEN_FLAG=""
|
|
elif [[ "${SKIP_BROKEN}" == "true" ]]; then
|
|
SKIP_BROKEN_FLAG="--skip-broken"
|
|
fi
|
|
|
|
# Get if 'allow-erasing-packages' is provided for group-install
|
|
ALLOW_ERASING=$(echo "${1}" | jq -r 'try .["group-install"].["allow-erasing-packages"]')
|
|
|
|
if [[ -z "${ALLOW_ERASING}" ]] || [[ "${ALLOW_ERASING}" == "null" ]] || [[ "${ALLOW_ERASING}" == "false" ]]; then
|
|
ALLOW_ERASING_FLAG=""
|
|
elif [[ "${ALLOW_ERASING}" == "true" ]]; then
|
|
ALLOW_ERASING_FLAG="--allowerasing"
|
|
fi
|
|
|
|
if [[ ${#GROUP_INSTALL[@]} -gt 0 && ${#GROUP_REMOVE[@]} -gt 0 ]]; then
|
|
echo "Removing & Installing RPM groups"
|
|
echo "Removing: ${GROUP_REMOVE[*]}"
|
|
echo "Installing: ${GROUP_INSTALL[*]}"
|
|
dnf -y group remove "${GROUP_REMOVE[@]}"
|
|
dnf -y ${WEAK_DEPS_FLAG} group install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${GROUP_INSTALL[@]}"
|
|
elif [[ ${#GROUP_INSTALL[@]} -gt 0 ]]; then
|
|
echo "Installing RPM groups"
|
|
echo "Installing: ${GROUP_INSTALL[*]}"
|
|
dnf -y ${WEAK_DEPS_FLAG} group install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${GROUP_INSTALL[@]}"
|
|
elif [[ ${#GROUP_REMOVE[@]} -gt 0 ]]; then
|
|
echo "Removing RPM groups"
|
|
echo "Removing: ${GROUP_REMOVE[*]}"
|
|
dnf -y group remove "${GROUP_REMOVE[@]}"
|
|
fi
|
|
|
|
get_json_array INSTALL_PKGS 'try .["install"].["packages"][]' "${1}"
|
|
get_json_array REMOVE_PKGS 'try .["remove"].["packages"][]' "${1}"
|
|
|
|
# Get if 'install-weak-dependencies' is provided for package install
|
|
WEAK_DEPENDENCIES=$(echo "${1}" | jq -r 'try .["install"].["install-weak-dependencies"]')
|
|
|
|
if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then
|
|
WEAK_DEPS_FLAG="--setopt=install_weak_deps=True"
|
|
elif [[ "${WEAK_DEPENDENCIES}" == "false" ]]; then
|
|
WEAK_DEPS_FLAG="--setopt=install_weak_deps=False"
|
|
fi
|
|
|
|
# Get if 'skip-unavailable-packages' is provided for package install
|
|
SKIP_UNAVAILABLE=$(echo "${1}" | jq -r 'try .["install"].["skip-unavailable-packages"]')
|
|
|
|
if [[ -z "${SKIP_UNAVAILABLE}" ]] || [[ "${SKIP_UNAVAILABLE}" == "null" ]] || [[ "${SKIP_UNAVAILABLE}" == "false" ]]; then
|
|
SKIP_UNAVAILABLE_FLAG=""
|
|
elif [[ "${SKIP_UNAVAILABLE}" == "true" ]]; then
|
|
SKIP_UNAVAILABLE_FLAG="--skip-unavailable"
|
|
fi
|
|
|
|
# Get if 'skip-broken-packages' is provided for package install
|
|
SKIP_BROKEN=$(echo "${1}" | jq -r 'try .["install"].["skip-broken-packages"]')
|
|
|
|
if [[ -z "${SKIP_BROKEN}" ]] || [[ "${SKIP_BROKEN}" == "null" ]] || [[ "${SKIP_BROKEN}" == "false" ]]; then
|
|
SKIP_BROKEN_FLAG=""
|
|
elif [[ "${SKIP_BROKEN}" == "true" ]]; then
|
|
SKIP_BROKEN_FLAG="--skip-broken"
|
|
fi
|
|
|
|
# Get if 'allow-erasing-packages' is provided for package install
|
|
ALLOW_ERASING=$(echo "${1}" | jq -r 'try .["install"].["allow-erasing-packages"]')
|
|
|
|
if [[ -z "${ALLOW_ERASING}" ]] || [[ "${ALLOW_ERASING}" == "null" ]] || [[ "${ALLOW_ERASING}" == "false" ]]; then
|
|
ALLOW_ERASING_FLAG=""
|
|
elif [[ "${ALLOW_ERASING}" == "true" ]]; then
|
|
ALLOW_ERASING_FLAG="--allowerasing"
|
|
fi
|
|
|
|
# Get if 'remove-unused-dependencies' is provided for package removal
|
|
REMOVE_UNUSED_DEPS=$(echo "${1}" | jq -r 'try .["remove"].["remove-unused-dependencies"]')
|
|
|
|
if [[ -z "${REMOVE_UNUSED_DEPS}" ]] || [[ "${REMOVE_UNUSED_DEPS}" == "null" ]] || [[ "${REMOVE_UNUSED_DEPS}" == "true" ]]; then
|
|
REMOVE_UNUSED_DEPS_FLAG=""
|
|
elif [[ "${REMOVE_UNUSED_DEPS}" == "false" ]]; then
|
|
REMOVE_UNUSED_DEPS_FLAG="--no-autoremove"
|
|
fi
|
|
|
|
CLASSIC_INSTALL=false
|
|
HTTPS_INSTALL=false
|
|
LOCAL_INSTALL=false
|
|
|
|
# Sort classic, URL & local install packages
|
|
if [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then
|
|
for i in "${!INSTALL_PKGS[@]}"; do
|
|
PKG="${INSTALL_PKGS[$i]}"
|
|
if [[ "${PKG}" =~ ^https?:\/\/.* ]]; then
|
|
INSTALL_PKGS[$i]="${PKG//%OS_VERSION%/${OS_VERSION}}"
|
|
HTTPS_INSTALL=true
|
|
HTTPS_PKGS+=("${INSTALL_PKGS[$i]}")
|
|
elif [[ ! "${PKG}" =~ ^https?:\/\/.* ]] && [[ -f "${CONFIG_DIRECTORY}/dnf/${PKG}" ]]; then
|
|
LOCAL_INSTALL=true
|
|
LOCAL_PKGS+=("${CONFIG_DIRECTORY}/dnf/${PKG}")
|
|
else
|
|
CLASSIC_INSTALL=true
|
|
CLASSIC_PKGS+=("${PKG}")
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Function to inform the user about which type of packages is he installing
|
|
echo_rpm_install() {
|
|
if ${CLASSIC_INSTALL}; then
|
|
echo "Installing: ${CLASSIC_PKGS[*]}"
|
|
fi
|
|
if ${HTTPS_INSTALL}; then
|
|
echo "Installing package(s) directly from URL: ${HTTPS_PKGS[*]}"
|
|
fi
|
|
if ${LOCAL_INSTALL}; then
|
|
echo "Installing local package(s): ${LOCAL_PKGS[*]}"
|
|
fi
|
|
}
|
|
|
|
# Remove & install RPM packages
|
|
if [[ ${#INSTALL_PKGS[@]} -gt 0 && ${#REMOVE_PKGS[@]} -gt 0 ]]; then
|
|
echo "Removing & Installing RPMs"
|
|
echo "Removing: ${REMOVE_PKGS[*]}"
|
|
echo_rpm_install
|
|
dnf -y remove ${REMOVE_UNUSED_DEPS_FLAG} "${REMOVE_PKGS[@]}"
|
|
dnf -y ${WEAK_DEPS_FLAG} install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${INSTALL_PKGS[@]}"
|
|
elif [[ ${#INSTALL_PKGS[@]} -gt 0 ]]; then
|
|
echo "Installing RPMs"
|
|
echo_rpm_install
|
|
dnf -y ${WEAK_DEPS_FLAG} install --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} "${INSTALL_PKGS[@]}"
|
|
elif [[ ${#REMOVE_PKGS[@]} -gt 0 ]]; then
|
|
echo "Removing RPMs"
|
|
echo "Removing: ${REMOVE_PKGS[*]}"
|
|
dnf -y remove ${REMOVE_UNUSED_DEPS_FLAG} "${REMOVE_PKGS[@]}"
|
|
fi
|
|
|
|
get_json_array REPLACE 'try .["replace"][]' "$1"
|
|
|
|
# Replace RPM packages from any repository
|
|
if [[ ${#REPLACE[@]} -gt 0 ]]; then
|
|
for REPLACEMENT in "${REPLACE[@]}"; do
|
|
|
|
# Get repository
|
|
REPO=$(echo "${REPLACEMENT}" | jq -r 'try .["from-repo"]')
|
|
REPO="${REPO//%OS_VERSION%/${OS_VERSION}}"
|
|
REPO="${REPO//[$'\t\r\n ']}"
|
|
|
|
# Ensure repository is provided
|
|
if [[ "${REPO}" == "null" ]] || [[ -z "${REPO}" ]]; then
|
|
echo "ERROR: Key 'from-repo' was declared, but repository URL was not provided."
|
|
exit 1
|
|
fi
|
|
|
|
# Get packages to replace
|
|
get_json_array PACKAGES 'try .["packages"][]' "${REPLACEMENT}"
|
|
|
|
# Ensure packages are provided
|
|
if [[ ${#PACKAGES[@]} -eq 0 ]]; then
|
|
echo "ERROR: No packages were provided for repository '${REPO}'."
|
|
exit 1
|
|
fi
|
|
|
|
# Get if 'install-weak-dependencies' is provided for package replace
|
|
WEAK_DEPENDENCIES=$(echo "${REPLACEMENT}" | jq -r 'try .["install-weak-dependencies"]')
|
|
|
|
if [[ -z "${WEAK_DEPENDENCIES}" ]] || [[ "${WEAK_DEPENDENCIES}" == "null" ]] || [[ "${WEAK_DEPENDENCIES}" == "true" ]]; then
|
|
WEAK_DEPS_FLAG="--setopt=install_weak_deps=True"
|
|
elif [[ "${WEAK_DEPENDENCIES}" == "false" ]]; then
|
|
WEAK_DEPS_FLAG="--setopt=install_weak_deps=False"
|
|
fi
|
|
|
|
# Get if 'skip-unavailable-packages' is provided for package replace
|
|
SKIP_UNAVAILABLE=$(echo "${REPLACEMENT}" | jq -r 'try .["skip-unavailable-packages"]')
|
|
|
|
if [[ -z "${SKIP_UNAVAILABLE}" ]] || [[ "${SKIP_UNAVAILABLE}" == "null" ]] || [[ "${SKIP_UNAVAILABLE}" == "false" ]]; then
|
|
SKIP_UNAVAILABLE_FLAG=""
|
|
elif [[ "${SKIP_UNAVAILABLE}" == "true" ]]; then
|
|
SKIP_UNAVAILABLE_FLAG="--skip-unavailable"
|
|
fi
|
|
|
|
# Get if 'skip-broken-packages' is provided for package replace
|
|
SKIP_BROKEN=$(echo "${REPLACEMENT}" | jq -r 'try .["skip-broken-packages"]')
|
|
|
|
if [[ -z "${SKIP_BROKEN}" ]] || [[ "${SKIP_BROKEN}" == "null" ]] || [[ "${SKIP_BROKEN}" == "false" ]]; then
|
|
SKIP_BROKEN_FLAG=""
|
|
elif [[ "${SKIP_BROKEN}" == "true" ]]; then
|
|
SKIP_BROKEN_FLAG="--skip-broken"
|
|
fi
|
|
|
|
# Get if 'allow-erasing-packages' is provided for package replace
|
|
ALLOW_ERASING=$(echo "${REPLACEMENT}" | jq -r 'try .["allow-erasing-packages"]')
|
|
|
|
if [[ -z "${ALLOW_ERASING}" ]] || [[ "${ALLOW_ERASING}" == "null" ]] || [[ "${ALLOW_ERASING}" == "false" ]]; then
|
|
ALLOW_ERASING_FLAG=""
|
|
elif [[ "${ALLOW_ERASING}" == "true" ]]; then
|
|
ALLOW_ERASING_FLAG="--allowerasing"
|
|
fi
|
|
|
|
echo "Replacing packages from repository: '${REPO}'"
|
|
echo "Replacing: ${PACKAGES[*]}"
|
|
|
|
dnf -y ${WEAK_DEPS_FLAG} distro-sync --refresh ${SKIP_UNAVAILABLE_FLAG} ${SKIP_BROKEN_FLAG} ${ALLOW_ERASING_FLAG} --repo "${REPO}" "${PACKAGES[@]}"
|
|
|
|
done
|
|
fi
|