Skip to content

Extending support of powershell feature for AlmaLinux #1303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 124 additions & 16 deletions src/powershell/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,89 @@ POWERSHELL_MODULES="${MODULES:-""}"
POWERSHELL_PROFILE_URL="${POWERSHELLPROFILEURL}"

MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
POWERSHELL_ARCHIVE_ARCHITECTURES="amd64"
#MICROSOFT_GPG_KEYS_URI=$(curl https://packages.microsoft.com/keys/microsoft.asc -o /usr/share/keyrings/microsoft-archive-keyring.gpg)
POWERSHELL_ARCHIVE_ARCHITECTURES_UBUNTU="amd64"
POWERSHELL_ARCHIVE_ARCHITECTURES_ALMALINUX="x86_64"
POWERSHELL_ARCHIVE_VERSION_CODENAMES="stretch buster bionic focal bullseye jammy bookworm noble"

#These key servers are used to verify the authenticity of packages and repositories.
#keyservers for ubuntu and almalinux are different so we need to specify both
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"
keyserver hkp://keyserver.pgp.com
keyserver hkp://keyserver.fedoraproject.org
keyserver hkps://keys.openpgp.org
keyserver hkp://pgp.mit.edu
keyserver hkp://keyserver.redhat.com"


if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi

# Clean up package manager cache
clean_cache() {
if [ -d "/var/cache/apt" ]; then
apt-get clean
fi
if [ -d "/var/cache/dnf" ]; then
rm -rf /var/cache/dnf/*
fi
}
# Install dependencies for RHEL/CentOS/AlmaLinux (DNF-based systems)
install_using_dnf() {
dnf remove -y curl-minimal
dnf install -y curl gnupg2 ca-certificates dnf-plugins-core
dnf clean all
dnf makecache
curl --version
}

# Install PowerShell on RHEL/CentOS/AlmaLinux-based systems (DNF)
install_powershell_dnf() {
# Install wget, if not already installed
dnf install -y wget

# Download Microsoft GPG key
curl https://packages.microsoft.com/keys/microsoft.asc -o /usr/share/keyrings/microsoft-archive-keyring.gpg
ls -l /usr/share/keyrings/microsoft-archive-keyring.gpg

# Install necessary dependencies
dnf install -y krb5-libs libicu openssl-libs zlib

# Add Microsoft PowerShell repository
curl "https://packages.microsoft.com/config/rhel/9.0/prod.repo" > /etc/yum.repos.d/microsoft.repo

# Install PowerShell
dnf install --assumeyes powershell
}


# Detect the package manager and OS
detect_package_manager() {
if [ -f /etc/os-release ]; then
. /etc/os-release
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
echo "Detected Debian/Ubuntu-based system"
install_using_apt
install_pwsh
elif [[ "$ID" == "centos" || "$ID" == "rhel" || "$ID" == "almalinux" ]]; then
echo "Detected RHEL/CentOS/AlmaLinux-based system"
install_using_dnf
install_powershell_dnf
install_pwsh
else
echo "Unsupported Linux distribution: $ID"
exit 1
fi
else
echo "Could not detect OS"
exit 1
fi
}

# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
Expand Down Expand Up @@ -72,19 +143,43 @@ apt_get_update()
}

# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update
apt-get -y install --no-install-recommends "$@"
fi
check_packages() {
if command -v dpkg > /dev/null 2>&1; then
# If dpkg exists, assume APT-based system (Debian/Ubuntu)
for package in "$@"; do
if ! dpkg -s "$package" > /dev/null 2>&1; then
echo "Package $package not installed. Installing using apt-get..."
apt-get update
apt-get install -y --no-install-recommends "$package"
else
echo "Package $package is already installed (APT)."
fi
done
elif command -v dnf > /dev/null 2>&1; then
for package in "$@"; do
if ! dnf list installed "$package" > /dev/null 2>&1; then
echo "Package $package not installed. Installing using dnf..."
dnf install -y "$package"
else
echo "Package $package is already installed (DNF)."
fi
done
else
echo "Unsupported package manager. Neither APT nor DNF found."
return 1
fi


}

install_using_apt() {
# Install dependencies
check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install

curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list


# Update lists
apt-get update -yq
Expand Down Expand Up @@ -201,7 +296,8 @@ install_using_github() {
if ! type git > /dev/null 2>&1; then
check_packages git
fi
if [ "${architecture}" = "amd64" ]; then

if [ "${architecture}" = "amd64" ]; then
architecture="x64"
fi
pwsh_url="https://github.com/PowerShell/PowerShell"
Expand All @@ -210,9 +306,13 @@ install_using_github() {
if grep -q "Not Found" "${powershell_filename}"; then
install_prev_pwsh $pwsh_url
fi

# downlaod the latest version of powershell and extracting the file to powershell directory
wget https://github.com/PowerShell/PowerShell/releases/download/v${POWERSHELL_VERSION}/${powershell_filename}
mkdir ~/powershell
tar -xvf powershell-${POWERSHELL_VERSION}-linux-x64.tar.gz -C ~/powershell


# Ugly - but only way to get sha256 is to parse release HTML. Remove newlines and tags, then look for filename followed by 64 hex characters.
curl -sSL -o "release.html" "https://github.com/PowerShell/PowerShell/releases/tag/v${POWERSHELL_VERSION}"
powershell_archive_sha256="$(cat release.html | tr '\n' ' ' | sed 's|<[^>]*>||g' | grep -oP "${powershell_filename}\s+\K[0-9a-fA-F]{64}" || echo '')"
if [ -z "${powershell_archive_sha256}" ]; then
echo "(!) WARNING: Failed to retrieve SHA256 for archive. Skipping validaiton."
Expand All @@ -233,14 +333,22 @@ if ! type pwsh >/dev/null 2>&1; then

# Source /etc/os-release to get OS info
. /etc/os-release
architecture="$(dpkg --print-architecture)"
architecture="$(uname -m)"
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
POWERSHELL_ARCHIVE_ARCHITECTURES="${POWERSHELL_ARCHIVE_ARCHITECTURES_UBUNTU}"
elif [[ "$ID" == "centos" || "$ID" == "rhel" || "$ID" == "almalinux" ]]; then
POWERSHELL_ARCHIVE_ARCHITECTURES="${POWERSHELL_ARCHIVE_ARCHITECTURES_ALMALINUX}"
fi

if [[ "${POWERSHELL_ARCHIVE_ARCHITECTURES}" = *"${architecture}"* ]] && [[ "${POWERSHELL_ARCHIVE_VERSION_CODENAMES}" = *"${VERSION_CODENAME}"* ]]; then
if [[ "${POWERSHELL_ARCHIVE_ARCHITECTURES}" = *"${POWERSHELL_ARCHIVE_ARCHITECTURES_UBUNTU}"* ]] && [[ "${POWERSHELL_ARCHIVE_VERSION_CODENAMES}" = *"${VERSION_CODENAME}"* ]]; then
install_using_apt || use_github="true"
else
use_github="true"
fi
elif [[ "${POWERSHELL_ARCHIVE_ARCHITECTURES}" = *"${POWERSHELL_ARCHIVE_ARCHITECTURES_ALMALINUX}"* ]]; then
install_using_dnf && install_powershell_dnf || use_github="true"

else
use_github="true"
fi

if [ "${use_github}" = "true" ]; then
echo "Attempting install from GitHub release..."
install_using_github
Expand Down Expand Up @@ -282,4 +390,4 @@ fi
# Clean up
rm -rf /var/lib/apt/lists/*

echo "Done!"
echo "Done!"
18 changes: 18 additions & 0 deletions test/powershell/powershell_alma_linux.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

set -e

# Import test library for `check` command
source dev-container-features-test-lib

# Extension-specific tests
check "pwsh file is symlink" bash -c "[ -L /usr/bin/pwsh ]"
check "pwsh symlink is registered as shell" bash -c "[ $(grep -c '/usr/bin/pwsh' /etc/shells) -ge 1 ]"
check "pwsh target is correct" bash -c "[ $(readlink /usr/bin/pwsh) = /opt/microsoft/powershell/7/pwsh ]"
check "pwsh owner is root" bash -c "[ $(stat -c %U /opt/microsoft/powershell/7/pwsh) = root ]"
check "pwsh group is root" bash -c "[ $(stat -c %G /opt/microsoft/powershell/7/pwsh) = root ]"
check "pwsh file mode is -rwxr-xr-x" bash -c "[ $(stat -c '%A' /opt/microsoft/powershell/7/pwsh) = '-rwxr-xr-x' ]"
check "pwsh is in PATH" bash -c "command -v pwsh"

# Report result
reportResults
6 changes: 6 additions & 0 deletions test/powershell/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,11 @@
"features": {
"powershell": {}
}
},
"powershell_alma_linux": {
"image": "almalinux:9",
"features": {
"powershell": {}
}
}
}