Skip to content
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

Add RHEL support to go feature #846

Merged
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
2 changes: 1 addition & 1 deletion src/go/NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

## OS Support

This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, and RockyLinux distributions with the apt, yum, dnf, or microdnf package manager installed.

`bash` is required to execute the `install.sh` script.
4 changes: 2 additions & 2 deletions src/go/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "go",
"version": "1.2.2",
"version": "1.3.0",
"name": "Go",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/go",
"description": "Installs Go and common Go utilities. Auto-detects latest version and installs needed dependencies.",
Expand Down Expand Up @@ -44,4 +44,4 @@
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
}
}
175 changes: 139 additions & 36 deletions src/go/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,60 @@ GO_GPG_KEY_URI="https://dl.google.com/linux/linux_signing_key.pub"

set -e

# Clean up
rm -rf /var/lib/apt/lists/*

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

# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh

# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
# Bring in ID, ID_LIKE, VERSION_ID, VERSION_CODENAME
. /etc/os-release
# Get an adjusted ID independent of distro variants
MAJOR_VERSION_ID=$(echo ${VERSION_ID} | cut -d . -f 1)
if [ "${ID}" = "debian" ] || [ "${ID_LIKE}" = "debian" ]; then
ADJUSTED_ID="debian"
elif [[ "${ID}" = "rhel" || "${ID}" = "fedora" || "${ID}" = "mariner" || "${ID_LIKE}" = *"rhel"* || "${ID_LIKE}" = *"fedora"* || "${ID_LIKE}" = *"mariner"* ]]; then
ADJUSTED_ID="rhel"
if [[ "${ID}" = "rhel" ]] || [[ "${ID}" = *"alma"* ]] || [[ "${ID}" = *"rocky"* ]]; then
VERSION_CODENAME="rhel${MAJOR_VERSION_ID}"
else
VERSION_CODENAME="${ID}${MAJOR_VERSION_ID}"
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
else
echo "Linux distro ${ID} not supported."
exit 1
fi

# Setup INSTALL_CMD & PKG_MGR_CMD
if type apt-get > /dev/null 2>&1; then
PKG_MGR_CMD=apt-get
INSTALL_CMD="${PKG_MGR_CMD} -y install --no-install-recommends"
elif type microdnf > /dev/null 2>&1; then
PKG_MGR_CMD=microdnf
INSTALL_CMD="${PKG_MGR_CMD} ${INSTALL_CMD_ADDL_REPOS} -y install --refresh --best --nodocs --noplugins --setopt=install_weak_deps=0"
elif type dnf > /dev/null 2>&1; then
PKG_MGR_CMD=dnf
INSTALL_CMD="${PKG_MGR_CMD} ${INSTALL_CMD_ADDL_REPOS} -y install --refresh --best --nodocs --noplugins --setopt=install_weak_deps=0"
else
PKG_MGR_CMD=yum
INSTALL_CMD="${PKG_MGR_CMD} ${INSTALL_CMD_ADDL_REPOS} -y install --noplugins --setopt=install_weak_deps=0"
fi

# Clean up
clean_up() {
case ${ADJUSTED_ID} in
debian)
rm -rf /var/lib/apt/lists/*
;;
rhel)
rm -rf /var/cache/dnf/* /var/cache/yum/*
rm -rf /tmp/yum.log
rm -rf ${GPG_INSTALL_PATH}
;;
esac
}
clean_up


# 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 @@ -84,29 +108,108 @@ find_version_from_git_tags() {
echo "${variable_name}=${!variable_name}"
}

apt_get_update()
{
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
pkg_mgr_update() {
case $ADJUSTED_ID in
debian)
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
${PKG_MGR_CMD} update -y
fi
;;
rhel)
if [ ${PKG_MGR_CMD} = "microdnf" ]; then
if [ "$(ls /var/cache/yum/* 2>/dev/null | wc -l)" = 0 ]; then
echo "Running ${PKG_MGR_CMD} makecache ..."
${PKG_MGR_CMD} makecache
fi
else
if [ "$(ls /var/cache/${PKG_MGR_CMD}/* 2>/dev/null | wc -l)" = 0 ]; then
echo "Running ${PKG_MGR_CMD} check-update ..."
set +e
${PKG_MGR_CMD} check-update
rc=$?
if [ $rc != 0 ] && [ $rc != 100 ]; then
exit 1
fi
set -e
fi
fi
;;
esac
}

# 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
case ${ADJUSTED_ID} in
debian)
if ! dpkg -s "$@" > /dev/null 2>&1; then
pkg_mgr_update
${INSTALL_CMD} "$@"
fi
;;
rhel)
if ! rpm -q "$@" > /dev/null 2>&1; then
pkg_mgr_update
${INSTALL_CMD} "$@"
fi
;;
esac
}

# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh

# Some distributions do not install awk by default (e.g. Mariner)
if ! type awk >/dev/null 2>&1; then
check_packages awk
fi

# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi

export DEBIAN_FRONTEND=noninteractive

# Install curl, tar, git, other dependencies if missing
check_packages curl ca-certificates gnupg2 tar g++ gcc libc6-dev make pkg-config
check_packages ca-certificates gnupg2 tar gcc make pkg-config

if [ $ADJUSTED_ID = "debian" ]; then
check_packages g++ libc6-dev
else
check_packages gcc-c++ glibc-devel
fi
# Install curl, git, other dependencies if missing
if ! type curl > /dev/null 2>&1; then
check_packages curl
fi
if ! type git > /dev/null 2>&1; then
check_packages git
fi
# Some systems, e.g. Mariner, still a few more packages
if ! type as > /dev/null 2>&1; then
check_packages binutils
fi
if ! [ -f /usr/include/linux/errno.h ]; then
check_packages kernel-headers
fi
# Minimal RHEL install may need findutils installed
if ! [ -f /usr/bin/find ]; then
check_packages findutils
fi

# Get closest match for version number specified
find_version_from_git_tags TARGET_GO_VERSION "https://go.googlesource.com/go" "tags/go" "." "true"
Expand All @@ -128,7 +231,7 @@ fi
usermod -a -G golang "${USERNAME}"
mkdir -p "${TARGET_GOROOT}" "${TARGET_GOPATH}"

if [[ "${TARGET_GO_VERSION}" != "none" ]] && [[ "$(go version)" != *"${TARGET_GO_VERSION}"* ]]; then
if [[ "${TARGET_GO_VERSION}" != "none" ]] && [[ "$(go version 2>/dev/null)" != *"${TARGET_GO_VERSION}"* ]]; then
# Use a temporary location for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
Expand Down Expand Up @@ -230,6 +333,6 @@ find "${TARGET_GOROOT}" -type d -print0 | xargs -n 1 -0 chmod g+s
find "${TARGET_GOPATH}" -type d -print0 | xargs -n 1 -0 chmod g+s

# Clean up
rm -rf /var/lib/apt/lists/*
clean_up

echo "Done!"
28 changes: 28 additions & 0 deletions test/go/install_go_alma-8-minimal.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# go
check "version" go version

# revive
check "revive version" revive --version
check "revive is installed at correct path" bash -c "type revive | grep /go/bin/revive"

# gomodifytags
check "gomodifytags is installed at correct path" bash -c "type gomodifytags | grep /go/bin/gomodifytags"

# goplay
check "goplay is installed at correct path" bash -c "type goplay | grep /go/bin/goplay"

# gotests
check "gotests is installed at correct path" bash -c "type gotests | grep /go/bin/gotests"

# impl
check "impl is installed at correct path" bash -c "type impl | grep /go/bin/impl"

# Report result
reportResults
28 changes: 28 additions & 0 deletions test/go/install_go_alma-8.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# go
check "version" go version

# revive
check "revive version" revive --version
check "revive is installed at correct path" bash -c "type revive | grep /go/bin/revive"

# gomodifytags
check "gomodifytags is installed at correct path" bash -c "type gomodifytags | grep /go/bin/gomodifytags"

# goplay
check "goplay is installed at correct path" bash -c "type goplay | grep /go/bin/goplay"

# gotests
check "gotests is installed at correct path" bash -c "type gotests | grep /go/bin/gotests"

# impl
check "impl is installed at correct path" bash -c "type impl | grep /go/bin/impl"

# Report result
reportResults
28 changes: 28 additions & 0 deletions test/go/install_go_alma-9-minimal.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# go
check "version" go version

# revive
check "revive version" revive --version
check "revive is installed at correct path" bash -c "type revive | grep /go/bin/revive"

# gomodifytags
check "gomodifytags is installed at correct path" bash -c "type gomodifytags | grep /go/bin/gomodifytags"

# goplay
check "goplay is installed at correct path" bash -c "type goplay | grep /go/bin/goplay"

# gotests
check "gotests is installed at correct path" bash -c "type gotests | grep /go/bin/gotests"

# impl
check "impl is installed at correct path" bash -c "type impl | grep /go/bin/impl"

# Report result
reportResults
28 changes: 28 additions & 0 deletions test/go/install_go_alma-9.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# go
check "version" go version

# revive
check "revive version" revive --version
check "revive is installed at correct path" bash -c "type revive | grep /go/bin/revive"

# gomodifytags
check "gomodifytags is installed at correct path" bash -c "type gomodifytags | grep /go/bin/gomodifytags"

# goplay
check "goplay is installed at correct path" bash -c "type goplay | grep /go/bin/goplay"

# gotests
check "gotests is installed at correct path" bash -c "type gotests | grep /go/bin/gotests"

# impl
check "impl is installed at correct path" bash -c "type impl | grep /go/bin/impl"

# Report result
reportResults
28 changes: 28 additions & 0 deletions test/go/install_go_centos-7.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# go
check "version" go version

# revive
check "revive version" revive --version
check "revive is installed at correct path" bash -c "type revive | grep /go/bin/revive"

# gomodifytags
check "gomodifytags is installed at correct path" bash -c "type gomodifytags | grep /go/bin/gomodifytags"

# goplay
check "goplay is installed at correct path" bash -c "type goplay | grep /go/bin/goplay"

# gotests
check "gotests is installed at correct path" bash -c "type gotests | grep /go/bin/gotests"

# impl
check "impl is installed at correct path" bash -c "type impl | grep /go/bin/impl"

# Report result
reportResults
Loading