Unverified Commit 30e03b62 authored by Jeff Putsch's avatar Jeff Putsch Committed by GitHub

Add RHEL support to the python feature (#830)

* install gpg2.22 on centos 7 when installing python

* RHEL support, exisiting tests pass, new RHEL tests pass.

* add tests, cleanup install organization

* update testing to include RHEL tests

* update testing to include RHEL tests

* undo addition of installing additional pip modules

* fix errors installing os-provided Python on recent Debian systems and on Mariner systems

* adjust to properly use newly installed python (PYTHON_SRC) instead of assuming "python" will work

* When installing pipx, check if python is marked as externally
managed. If so, add "--break-system-packages" to the pip install
flags.

This does not really breack system packages due to the setting of
PYTHONUSERBASE during the install of pipx, but does get us past
checks for installing python packages into the system python install.

* merge from main

* update check for managed python install. pass all tests.

* add "packages" option from PR #768

* remove "packages" option

* Address PR feedback, passes all tests locally.

* fix install error on centos

---------
Co-authored-by: 's avatarJeff Putsch <jputsch@analog.com>
parent 1592dd59
...@@ -67,7 +67,7 @@ jobs: ...@@ -67,7 +67,7 @@ jobs:
test-scenarios: test-scenarios:
needs: [detect-changes] needs: [detect-changes]
runs-on: ubuntu-latest runs-on: devcontainer-image-builder-ubuntu
continue-on-error: true continue-on-error: true
strategy: strategy:
matrix: matrix:
......
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
## OS Support ## 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. `bash` is required to execute the `install.sh` script.
{ {
"id": "python", "id": "python",
"version": "1.3.2", "version": "1.4.0",
"name": "Python", "name": "Python",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/python", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/python",
"description": "Installs the provided version of Python, as well as PIPX, and other common Python utilities. JupyterLab is conditionally installed with the python feature. Note: May require source code compilation.", "description": "Installs the provided version of Python, as well as PIPX, and other common Python utilities. JupyterLab is conditionally installed with the python feature. Note: May require source code compilation.",
...@@ -25,13 +25,23 @@ ...@@ -25,13 +25,23 @@
"installTools": { "installTools": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "Install common Python tools like pylint" "description": "Flag indicating whether or not to install the tools specified via the 'toolsToInstall' option. Default is 'true'."
},
"toolsToInstall": {
"type": "string",
"default": "flake8,autopep8,black,yapf,mypy,pydocstyle,pycodestyle,bandit,pipenv,virtualenv,pytest,pylint",
"description": "Comma-separated list of tools to install when 'installTools' is true. Defaults to a set of common Python tools like pylint."
}, },
"optimize": { "optimize": {
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "Optimize Python for performance when compiled (slow)" "description": "Optimize Python for performance when compiled (slow)"
}, },
"enableShared": {
"type": "boolean",
"default": false,
"description": "Enable building a shared Python library"
},
"installPath": { "installPath": {
"type": "string", "type": "string",
"default": "/usr/local/python", "default": "/usr/local/python",
...@@ -71,7 +81,7 @@ ...@@ -71,7 +81,7 @@
} }
}, },
"installsAfter": [ "installsAfter": [
"ghcr.io/devcontainers/features/common-utils", "ghcr.io/devcontainers/features/common-utils",
"ghcr.io/devcontainers/features/oryx" "ghcr.io/devcontainers/features/oryx"
] ]
} }
\ No newline at end of file
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
PYTHON_VERSION="${VERSION:-"latest"}" # 'system' or 'os-provided' checks the base image first, else installs 'latest' PYTHON_VERSION="${VERSION:-"latest"}" # 'system' or 'os-provided' checks the base image first, else installs 'latest'
INSTALL_PYTHON_TOOLS="${INSTALLTOOLS:-"true"}" INSTALL_PYTHON_TOOLS="${INSTALLTOOLS:-"true"}"
OPTIMIZE_BUILD_FROM_SOURCE="${OPTIMIZE:-"false"}" OPTIMIZE_BUILD_FROM_SOURCE="${OPTIMIZE:-"false"}"
ENABLE_SHARED_FROM_SOURCE="${ENABLESHARED:-"false"}"
PYTHON_INSTALL_PATH="${INSTALLPATH:-"/usr/local/python"}" PYTHON_INSTALL_PATH="${INSTALLPATH:-"/usr/local/python"}"
OVERRIDE_DEFAULT_VERSION="${OVERRIDEDEFAULTVERSION:-"true"}" OVERRIDE_DEFAULT_VERSION="${OVERRIDEDEFAULTVERSION:-"true"}"
...@@ -26,7 +27,10 @@ CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN="${CONFIGUREJUPYTERLABALLOWORIGIN:-""}" ...@@ -26,7 +27,10 @@ CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN="${CONFIGUREJUPYTERLABALLOWORIGIN:-""}"
# alongside PYTHON_VERSION, but not set as default. # alongside PYTHON_VERSION, but not set as default.
ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS:-""}" ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS:-""}"
DEFAULT_UTILS=("pylint" "flake8" "autopep8" "black" "yapf" "mypy" "pydocstyle" "pycodestyle" "bandit" "pipenv" "virtualenv" "pytest") # Comma-separated list of additional tools to be installed via pipx.
IFS="," read -r -a DEFAULT_UTILS <<< "${TOOLSTOINSTALL:-flake8,autopep8,black,yapf,mypy,pydocstyle,pycodestyle,bandit,pipenv,virtualenv,pytest}"
PYTHON_SOURCE_GPG_KEYS="64E628F8D684696D B26995E310250568 2D347EA6AA65421D FB9921286F5E1540 3A5CA953F73C700D 04C367C218ADD4FF 0EDDC5F26A45C816 6AF053F07D9DC8D2 C9BE28DEE6DF025C 126EB563A74B06BF D9866941EA5BBD71 ED9D77D5 A821E680E5FA6305" PYTHON_SOURCE_GPG_KEYS="64E628F8D684696D B26995E310250568 2D347EA6AA65421D FB9921286F5E1540 3A5CA953F73C700D 04C367C218ADD4FF 0EDDC5F26A45C816 6AF053F07D9DC8D2 C9BE28DEE6DF025C 126EB563A74B06BF D9866941EA5BBD71 ED9D77D5 A821E680E5FA6305"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
keyserver hkp://keyserver.ubuntu.com:80 keyserver hkp://keyserver.ubuntu.com:80
...@@ -37,44 +41,90 @@ KEYSERVER_PROXY="${HTTPPROXY:-"${HTTP_PROXY:-""}"}" ...@@ -37,44 +41,90 @@ KEYSERVER_PROXY="${HTTPPROXY:-"${HTTP_PROXY:-""}"}"
set -e set -e
# Clean up
rm -rf /var/lib/apt/lists/*
if [ "$(id -u)" -ne 0 ]; then 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.' echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1 exit 1
fi fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV. # Bring in ID, ID_LIKE, VERSION_ID, VERSION_CODENAME
rm -f /etc/profile.d/00-restore-env.sh . /etc/os-release
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh # Get an adjusted ID independent of distro variants
chmod +x /etc/profile.d/00-restore-env.sh 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
else
echo "Linux distro ${ID} not supported."
exit 1
fi
# Determine the appropriate non-root user # To find some devel packages, some rhel need to enable specific extra repos, but not on RedHat ubi images...
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then INSTALL_CMD_ADDL_REPO=""
USERNAME="" if [ ${ADJUSTED_ID} = "rhel" ] && [ ${ID} != "rhel" ]; then
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") if [ ${MAJOR_VERSION_ID} = "8" ]; then
for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do INSTALL_CMD_ADDL_REPOS="--enablerepo powertools"
if id -u ${CURRENT_USER} > /dev/null 2>&1; then elif [ ${MAJOR_VERSION_ID} = "9" ]; then
USERNAME=${CURRENT_USER} INSTALL_CMD_ADDL_REPOS="--enablerepo crb"
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi 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
updaterc() { updaterc() {
local _bashrc
local _zshrc
if [ "${UPDATE_RC}" = "true" ]; then if [ "${UPDATE_RC}" = "true" ]; then
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." case $ADJUSTED_ID in
if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then debian) echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
echo -e "$1" >> /etc/bash.bashrc _bashrc=/etc/bash.bashrc
_zshrc=/etc/zsh/zshrc
;;
rhel) echo "Updating /etc/bashrc and /etc/zshrc..."
_bashrc=/etc/bashrc
_zshrc=/etc/zshrc
;;
esac
if [[ "$(cat ${_bashrc})" != *"$1"* ]]; then
echo -e "$1" >> ${_bashrc}
fi fi
if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then if [ -f "${_zshrc}" ] && [[ "$(cat ${_zshrc})" != *"$1"* ]]; then
echo -e "$1" >> /etc/zsh/zshrc echo -e "$1" >> ${_zshrc}
fi fi
fi fi
} }
...@@ -83,6 +133,7 @@ updaterc() { ...@@ -83,6 +133,7 @@ updaterc() {
receive_gpg_keys() { receive_gpg_keys() {
local keys=${!1} local keys=${!1}
local keyring_args="" local keyring_args=""
local gpg_cmd="gpg"
if [ ! -z "$2" ]; then if [ ! -z "$2" ]; then
mkdir -p "$(dirname \"$2\")" mkdir -p "$(dirname \"$2\")"
keyring_args="--no-default-keyring --keyring $2" keyring_args="--no-default-keyring --keyring $2"
...@@ -116,6 +167,51 @@ receive_gpg_keys() { ...@@ -116,6 +167,51 @@ receive_gpg_keys() {
exit 1 exit 1
fi fi
} }
# RHEL7/CentOS7 has an older gpg that does not have dirmngr
# Iterate through keyservers until we have all the keys downloaded
receive_gpg_keys_centos7() {
local keys=${!1}
local keyring_args=""
local gpg_cmd="gpg"
if [ ! -z "$2" ]; then
mkdir -p "$(dirname \"$2\")"
keyring_args="--no-default-keyring --keyring $2"
fi
if [ ! -z "${KEYSERVER_PROXY}" ]; then
keyring_args="${keyring_args} --keyserver-options http-proxy=${KEYSERVER_PROXY}"
fi
# Use a temporary location for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
# GPG key download sometimes fails for some reason and retrying fixes it.
local retry_count=0
local gpg_ok="false"
num_keys=$(echo ${keys} | wc -w)
set +e
echo "(*) Downloading GPG keys..."
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ]; do
for keyserver in $(echo "${GPG_KEY_SERVERS}" | sed 's/keyserver //'); do
( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys --keyserver=${keyserver} ) 2>&1
downloaded_keys=$(gpg --list-keys | grep ^pub | wc -l)
if [[ ${num_keys} = ${downloaded_keys} ]]; then
gpg_ok="true"
break
fi
done
if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ ))
sleep 10s
fi
done
set -e
if [ "${gpg_ok}" = "false" ]; then
echo "(!) Failed to get gpg key."
exit 1
fi
}
# Figure out correct version of a three part version number is not passed # Figure out correct version of a three part version number is not passed
find_version_from_git_tags() { find_version_from_git_tags() {
...@@ -189,20 +285,52 @@ oryx_install() { ...@@ -189,20 +285,52 @@ oryx_install() {
fi fi
} }
apt_get_update() pkg_mgr_update() {
{ case $ADJUSTED_ID in
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then debian)
echo "Running apt-get update..." if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
apt-get update -y echo "Running apt-get update..."
fi ${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 # Checks if packages are installed and installs them if not
check_packages() { check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then case ${ADJUSTED_ID} in
apt_get_update debian)
apt-get -y install --no-install-recommends "$@" if ! dpkg -s "$@" > /dev/null 2>&1; then
fi pkg_mgr_update
${INSTALL_CMD} "$@"
fi
;;
rhel)
if ! rpm -q "$@" > /dev/null 2>&1; then
pkg_mgr_update
${INSTALL_CMD} "$@"
fi
;;
esac
} }
add_symlink() { add_symlink() {
...@@ -218,13 +346,30 @@ add_symlink() { ...@@ -218,13 +346,30 @@ add_symlink() {
fi fi
} }
install_openssl3() {
local _prefix=$1
mkdir /tmp/openssl3
(
cd /tmp/openssl3
openssl3_version="3.0"
# Find version using soft match
find_version_from_git_tags openssl3_version "https://github.com/openssl/openssl" "openssl-"
local tgz_filename="openssl-${openssl3_version}.tar.gz"
local tgz_url="https://github.com/openssl/openssl/releases/download/openssl-${openssl3_version}/${tgz_filename}"
echo "Downloading ${tgz_filename}..."
curl -sSL -o "/tmp/openssl3/${tgz_filename}" "${tgz_url}"
tar xzf ${tgz_filename}
cd openssl-${openssl3_version}
./config --prefix=${_prefix} --openssldir=${_prefix} --libdir=lib
make -j $(nproc)
make install_dev
)
rm -rf /tmp/openssl3
}
install_from_source() { install_from_source() {
VERSION=$1 VERSION=$1
echo "(*) Building Python ${VERSION} from source..." echo "(*) Building Python ${VERSION} from source..."
# Install prereqs if missing
check_packages curl ca-certificates gnupg2 tar make gcc libssl-dev zlib1g-dev libncurses5-dev \
libbz2-dev libreadline-dev libxml2-dev xz-utils libgdbm-dev tk-dev dirmngr \
libxmlsec1-dev libsqlite3-dev libffi-dev liblzma-dev uuid-dev
if ! type git > /dev/null 2>&1; then if ! type git > /dev/null 2>&1; then
check_packages git check_packages git
fi fi
...@@ -239,6 +384,17 @@ install_from_source() { ...@@ -239,6 +384,17 @@ install_from_source() {
exit 1 exit 1
fi fi
# Some platforms/os versions need modern versions of openssl installed
# via common package repositories, for now rhel-7 family, use case statement to
# make it easy to expand
case ${VERSION_CODENAME} in
centos7|rhel7)
check_packages perl-IPC-Cmd
install_openssl3 ${INSTALL_PATH}
ADDL_CONFIG_ARGS="--with-openssl=${INSTALL_PATH} --with-openssl-rpath=${INSTALL_PATH}/lib"
;;
esac
# Download tgz of source # Download tgz of source
mkdir -p /tmp/python-src ${INSTALL_PATH} mkdir -p /tmp/python-src ${INSTALL_PATH}
cd /tmp/python-src cd /tmp/python-src
...@@ -248,13 +404,21 @@ install_from_source() { ...@@ -248,13 +404,21 @@ install_from_source() {
curl -sSL -o "/tmp/python-src/${tgz_filename}" "${tgz_url}" curl -sSL -o "/tmp/python-src/${tgz_filename}" "${tgz_url}"
# Verify signature # Verify signature
receive_gpg_keys PYTHON_SOURCE_GPG_KEYS if [[ ${VERSION_CODENAME} = "centos7" ]] || [[ ${VERSION_CODENAME} = "rhel7" ]]; then
receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS
else
receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
fi
echo "Downloading ${tgz_filename}.asc..." echo "Downloading ${tgz_filename}.asc..."
curl -sSL -o "/tmp/python-src/${tgz_filename}.asc" "${tgz_url}.asc" curl -sSL -o "/tmp/python-src/${tgz_filename}.asc" "${tgz_url}.asc"
gpg --verify "${tgz_filename}.asc" gpg --verify "${tgz_filename}.asc"
# Update min protocol for testing only - https://bugs.python.org/issue41561 # Update min protocol for testing only - https://bugs.python.org/issue41561
cp /etc/ssl/openssl.cnf /tmp/python-src/ if [ -f /etc/pki/tls/openssl.cnf ]; then
cp /etc/pki/tls/openssl.cnf /tmp/python-src/
else
cp /etc/ssl/openssl.cnf /tmp/python-src/
fi
sed -i -E 's/MinProtocol[=\ ]+.*/MinProtocol = TLSv1.0/g' /tmp/python-src/openssl.cnf sed -i -E 's/MinProtocol[=\ ]+.*/MinProtocol = TLSv1.0/g' /tmp/python-src/openssl.cnf
export OPENSSL_CONF=/tmp/python-src/openssl.cnf export OPENSSL_CONF=/tmp/python-src/openssl.cnf
...@@ -262,11 +426,21 @@ install_from_source() { ...@@ -262,11 +426,21 @@ install_from_source() {
tar -xzf "/tmp/python-src/${tgz_filename}" -C "/tmp/python-src" --strip-components=1 tar -xzf "/tmp/python-src/${tgz_filename}" -C "/tmp/python-src" --strip-components=1
local config_args="" local config_args=""
if [ "${OPTIMIZE_BUILD_FROM_SOURCE}" = "true" ]; then if [ "${OPTIMIZE_BUILD_FROM_SOURCE}" = "true" ]; then
config_args="--enable-optimizations" config_args="${config_args} --enable-optimizations"
fi
if [ "${ENABLESHARED}" = "true" ]; then
config_args=" ${config_args} --enable-shared"
# need double-$: LDFLAGS ends up in Makefile $$ becomes $ when evaluated.
# backslash needed for shell that Make calls escape the $.
export LDFLAGS="${LDFLAGS} -Wl,-rpath="'\$$ORIGIN'"/../lib"
fi
if [ -n "${ADDL_CONFIG_ARGS}" ]; then
config_args="${config_args} ${ADDL_CONFIG_ARGS}"
fi fi
./configure --prefix="${INSTALL_PATH}" --with-ensurepip=install ${config_args} ./configure --prefix="${INSTALL_PATH}" --with-ensurepip=install ${config_args}
make -j 8 make -j 8
make install make install
cd /tmp cd /tmp
rm -rf /tmp/python-src ${GNUPGHOME} /tmp/vscdc-settings.env rm -rf /tmp/python-src ${GNUPGHOME} /tmp/vscdc-settings.env
...@@ -336,7 +510,15 @@ install_python() { ...@@ -336,7 +510,15 @@ install_python() {
version=$1 version=$1
# If the os-provided versions are "good enough", detect that and bail out. # If the os-provided versions are "good enough", detect that and bail out.
if [ ${version} = "os-provided" ] || [ ${version} = "system" ]; then if [ ${version} = "os-provided" ] || [ ${version} = "system" ]; then
check_packages python3 python3-doc python3-pip python3-venv python3-dev python3-tk if [ ${ADJUSTED_ID} = "debian" ]; then
check_packages python3 python3-doc python3-pip python3-venv python3-dev python3-tk
else
if [ ${ID} != "mariner" ]; then
check_packages python3 python3-pip python3-devel python3-tkinter
else
check_packages python3 python3-pip python3-devel
fi
fi
INSTALL_PATH="/usr" INSTALL_PATH="/usr"
local current_bin_path="${CURRENT_PATH}/bin" local current_bin_path="${CURRENT_PATH}/bin"
...@@ -355,7 +537,7 @@ install_python() { ...@@ -355,7 +537,7 @@ install_python() {
fi fi
should_install_from_source=false should_install_from_source=false
elif [ "$(dpkg --print-architecture)" = "amd64" ] && [ "${USE_ORYX_IF_AVAILABLE}" = "true" ] && type oryx > /dev/null 2>&1; then elif [ ${ADJUSTED_ID} = "debian" ] && [ "$(dpkg --print-architecture)" = "amd64" ] && [ "${USE_ORYX_IF_AVAILABLE}" = "true" ] && type oryx > /dev/null 2>&1; then
install_using_oryx $version || should_install_from_source=true install_using_oryx $version || should_install_from_source=true
else else
should_install_from_source=true should_install_from_source=true
...@@ -365,14 +547,120 @@ install_python() { ...@@ -365,14 +547,120 @@ install_python() {
fi fi
} }
python_is_externally_managed() {
local _python_cmd=$1
local python_stdlib_dir=$(
${_python_cmd} -c '
import sys
import sysconfig
sys.prefix == sys.base_prefix and print(sysconfig.get_path("stdlib", sysconfig.get_default_scheme()))'
)
if [ -f ${python_stdlib_dir}/EXTERNALLY-MANAGED ]; then
return 0
else
return 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
# 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
# Ensure apt is in non-interactive to avoid prompts # Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
# General requirements # General requirements
check_packages curl ca-certificates gnupg2 tar make gcc libssl-dev zlib1g-dev libncurses5-dev \
libbz2-dev libreadline-dev libxml2-dev xz-utils libgdbm-dev tk-dev dirmngr \
libxmlsec1-dev libsqlite3-dev libffi-dev liblzma-dev uuid-dev
REQUIRED_PKGS=""
case ${ADJUSTED_ID} in
debian)
REQUIRED_PKGS="${REQUIRED_PKGS} \
ca-certificates \
curl \
dirmngr \
gcc \
gnupg2 \
libbz2-dev \
libffi-dev \
libgdbm-dev \
liblzma-dev \
libncurses5-dev \
libreadline-dev \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
libxmlsec1-dev \
make \
tar \
tk-dev \
uuid-dev \
xz-utils \
zlib1g-dev"
;;
rhel)
REQUIRED_PKGS="${REQUIRED_PKGS} \
bzip2-devel \
ca-certificates \
findutils \
gcc \
gnupg2 \
libffi-devel \
libxml2-devel \
make \
ncurses-devel \
openssl-devel \
shadow-utils \
sqlite-devel \
tar \
which \
xz-devel \
xz \
zlib-devel"
if ! type curl >/dev/null 2>&1; then
REQUIRED_PKGS="${REQUIRED_PKGS} \
curl"
fi
# Mariner does not have tk-devel package available, RedHat ubi8 and ubi9 do not have tk-devel
if [ ${ID} != "mariner" ] && [ ${ID} != "rhel" ]; then
REQUIRED_PKGS="${REQUIRED_PKGS} \
tk-devel"
fi
# Redhat ubi8 and ubi9 do not have some packages by default, only add them
# if we're not on RedHat ...
if [ ${ID} != "rhel" ]; then
REQUIRED_PKGS="${REQUIRED_PKGS} \
gdbm-devel \
readline-devel \
uuid-devel \
xmlsec1-devel"
fi
;;
esac
check_packages ${REQUIRED_PKGS}
# Install Python from source if needed # Install Python from source if needed
if [ "${PYTHON_VERSION}" != "none" ]; then if [ "${PYTHON_VERSION}" != "none" ]; then
...@@ -410,12 +698,15 @@ if [ "${PYTHON_VERSION}" != "none" ]; then ...@@ -410,12 +698,15 @@ if [ "${PYTHON_VERSION}" != "none" ]; then
find "${PYTHON_INSTALL_PATH}" -type d -print0 | xargs -0 -n 1 chmod g+s find "${PYTHON_INSTALL_PATH}" -type d -print0 | xargs -0 -n 1 chmod g+s
PYTHON_SRC="${INSTALL_PATH}/bin/python3" PYTHON_SRC="${INSTALL_PATH}/bin/python3"
if ! type pip >/dev/null 2>&1 && type pip3 >/dev/null 2>&1; then
ln -s /usr/bin/pip3 /usr/bin/pip
fi
else else
PYTHON_SRC=$(which python) PYTHON_SRC=$(which python)
fi fi
# Install Python tools if needed # Install Python tools if needed
if [[ "${INSTALL_PYTHON_TOOLS}" = "true" ]] && [[ $(python --version) != "" ]]; then if [[ "${INSTALL_PYTHON_TOOLS}" = "true" ]] && [[ -n "${PYTHON_SRC}" ]]; then
echo 'Installing Python tools...' echo 'Installing Python tools...'
export PIPX_BIN_DIR="${PIPX_HOME}/bin" export PIPX_BIN_DIR="${PIPX_HOME}/bin"
PATH="${PATH}:${PIPX_BIN_DIR}" PATH="${PATH}:${PIPX_BIN_DIR}"
...@@ -432,20 +723,23 @@ if [[ "${INSTALL_PYTHON_TOOLS}" = "true" ]] && [[ $(python --version) != "" ]]; ...@@ -432,20 +723,23 @@ if [[ "${INSTALL_PYTHON_TOOLS}" = "true" ]] && [[ $(python --version) != "" ]];
find "${PIPX_HOME}" -type d -print0 | xargs -0 -n 1 chmod g+s find "${PIPX_HOME}" -type d -print0 | xargs -0 -n 1 chmod g+s
# Update pip if not using os provided python # Update pip if not using os provided python
if [[ $(python --version) != "" ]] || [[ ${PYTHON_VERSION} != "os-provided" ]] && [[ ${PYTHON_VERSION} != "system" ]] && [[ ${PYTHON_VERSION} != "none" ]]; then if [[ -n "${PYTHON_SRC}" ]] && [[ ${PYTHON_VERSION} != "os-provided" ]] && [[ ${PYTHON_VERSION} != "system" ]] && [[ ${PYTHON_VERSION} != "none" ]]; then
echo "Updating pip..." echo "Updating pip..."
python -m pip install --no-cache-dir --upgrade pip ${PYTHON_SRC} -m pip install --no-cache-dir --upgrade pip
fi fi
# Install tools # Install tools
echo "Installing Python tools..."
export PYTHONUSERBASE=/tmp/pip-tmp export PYTHONUSERBASE=/tmp/pip-tmp
export PIP_CACHE_DIR=/tmp/pip-tmp/cache export PIP_CACHE_DIR=/tmp/pip-tmp/cache
PIPX_DIR="" PIPX_DIR=""
if ! type pipx > /dev/null 2>&1; then if ! type pipx > /dev/null 2>&1; then
pip3 install --disable-pip-version-check --no-cache-dir --user pipx 2>&1 if python_is_externally_managed ${PYTHON_SRC}; then
/tmp/pip-tmp/bin/pipx install --pip-args=--no-cache-dir pipx check_packages pipx
PIPX_DIR="/tmp/pip-tmp/bin/" else
pip3 install --disable-pip-version-check --no-cache-dir --user pipx 2>&1
/tmp/pip-tmp/bin/pipx install --pip-args=--no-cache-dir pipx
PIPX_DIR="/tmp/pip-tmp/bin/"
fi
fi fi
for util in "${DEFAULT_UTILS[@]}"; do for util in "${DEFAULT_UTILS[@]}"; do
if ! type ${util} > /dev/null 2>&1; then if ! type ${util} > /dev/null 2>&1; then
...@@ -458,7 +752,7 @@ if [[ "${INSTALL_PYTHON_TOOLS}" = "true" ]] && [[ $(python --version) != "" ]]; ...@@ -458,7 +752,7 @@ if [[ "${INSTALL_PYTHON_TOOLS}" = "true" ]] && [[ $(python --version) != "" ]];
# Temporary: Removes “setup tools” metadata directory due to https://github.com/advisories/GHSA-r9hx-vwmv-q579 # Temporary: Removes “setup tools” metadata directory due to https://github.com/advisories/GHSA-r9hx-vwmv-q579
VULNERABLE_VERSIONS=("3.10" "3.11") VULNERABLE_VERSIONS=("3.10" "3.11")
RUN_TIME_PY_VER_DETECT=$(python --version 2>&1) RUN_TIME_PY_VER_DETECT=$(${PYTHON_SRC} --version 2>&1)
PY_MAJOR_MINOR_VER=${RUN_TIME_PY_VER_DETECT:7:4}; PY_MAJOR_MINOR_VER=${RUN_TIME_PY_VER_DETECT:7:4};
if [[ ${VULNERABLE_VERSIONS[*]} =~ $PY_MAJOR_MINOR_VER ]]; then if [[ ${VULNERABLE_VERSIONS[*]} =~ $PY_MAJOR_MINOR_VER ]]; then
rm -rf ${PIPX_HOME}/shared/lib/"python${PY_MAJOR_MINOR_VER}"/site-packages/setuptools-65.5.0.dist-info rm -rf ${PIPX_HOME}/shared/lib/"python${PY_MAJOR_MINOR_VER}"/site-packages/setuptools-65.5.0.dist-info
...@@ -502,6 +796,6 @@ if [ "${INSTALL_JUPYTERLAB}" = "true" ]; then ...@@ -502,6 +796,6 @@ if [ "${INSTALL_JUPYTERLAB}" = "true" ]; then
fi fi
# Clean up # Clean up
rm -rf /var/lib/apt/lists/* clean_up
echo "Done!" echo "Done!"
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Always run these checks as the non-root user
user="$(whoami)"
check "user" grep vscode <<< "$user"
# Check for an installation of JupyterLab
check "version" jupyter lab --version
# Check location of JupyterLab installation
packages="$(python3 -m pip list)"
check "location" grep jupyter <<< "$packages"
# Check for git extension
check "jupyterlab_git" grep jupyterlab_git <<< "$packages"
# Check for correct JupyterLab configuration
check "config" grep ".*.allow_origin = '*'" /home/vscode/.jupyter/jupyter_server_config.py
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "python version 3.11 installed as default" bash -c "python --version | grep 3.11"
check "python3 version 3.11 installed as default" bash -c "python3 --version | grep 3.11"
check "python version 3.10.5 installed" bash -c "ls -l /usr/local/python | grep 3.10.5"
check "python version 3.8 installed" bash -c "ls -l /usr/local/python | grep 3.8"
check "python version 3.9.13 installed" bash -c "ls -l /usr/local/python | grep 3.9.13"
# Check that tools can execute - make sure something didn't get messed up in this scenario
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "bandit" bandit --version
check "mypy" mypy --version
check "pipenv" pipenv --version
check "pytest" pytest --version
check "ruff" ruff --version
check "virtualenv" virtualenv --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pipenv" bash -c "which pipenv | grep /usr/local/py-utils/bin/pipenv"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
check "which ruff" bash -c "which ruff | grep /usr/local/py-utils/bin/ruff"
check "which virtualenv" bash -c "which virtualenv | grep /usr/local/py-utils/bin/virtualenv"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "bandit" bandit --version
check "mypy" mypy --version
check "pipenv" pipenv --version
check "pytest" pytest --version
check "ruff" ruff --version
check "virtualenv" virtualenv --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pipenv" bash -c "which pipenv | grep /usr/local/py-utils/bin/pipenv"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
check "which ruff" bash -c "which ruff | grep /usr/local/py-utils/bin/ruff"
check "which virtualenv" bash -c "which virtualenv | grep /usr/local/py-utils/bin/virtualenv"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Always run these checks as the non-root user
user="$(whoami)"
check "user" grep vscode <<< "$user"
# Check for an installation of JupyterLab
check "version" jupyter lab --version
# Check location of JupyterLab installation
packages="$(python3 -m pip list)"
check "location" grep jupyter <<< "$packages"
# Check for git extension
check "jupyterlab_git" grep jupyterlab_git <<< "$packages"
# Check for correct JupyterLab configuration
check "config" grep ".*.allow_origin = '*'" /home/vscode/.jupyter/jupyter_server_config.py
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "python3 is installed" python3 --version
check "python is installed" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "python3 is installed" python3 --version
check "python is installed" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Report result
reportResults
...@@ -78,10 +78,6 @@ checkVulnerableDir() ...@@ -78,10 +78,6 @@ checkVulnerableDir()
fi fi
} }
bash -c "echo -e -n '\n'";
bash -c "echo -e 'Files/Folders related to setuptools :-'";
bash -c "find / -name \"*setuptools*\";"
# only for 3.10 # only for 3.10
checkVulnerableDir "/usr/local/py-utils/shared/lib/python3.10/site-packages/setuptools-65.5.0.dist-info" "3.10" checkVulnerableDir "/usr/local/py-utils/shared/lib/python3.10/site-packages/setuptools-65.5.0.dist-info" "3.10"
......
...@@ -79,10 +79,6 @@ checkVulnerableDir() ...@@ -79,10 +79,6 @@ checkVulnerableDir()
fi fi
} }
bash -c "echo -e -n '\n'";
bash -c "echo -e 'Files/Folders related to setuptools :-'";
bash -c "find / -name \"*setuptools*\";"
# only for 3.11 # only for 3.11
checkVulnerableDir "/usr/local/py-utils/shared/lib/python3.11/site-packages/setuptools-65.5.0.dist-info" "3.11" checkVulnerableDir "/usr/local/py-utils/shared/lib/python3.11/site-packages/setuptools-65.5.0.dist-info" "3.11"
......
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Check compiled with "--enable-shared" -- python truth is opposite of the shells
# therefore we negate the check to get a '0' exit code when the python
# has been compiled with --enable-shared
check "python enable shared" /usr/local/python/current/bin/python -c 'import sys; import sysconfig; sys.exit(sysconfig.get_config_vars("Py_ENABLE_SHARED") != [1])'
# Report result
reportResults
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" python --version
check "pip is installed" pip --version
check "pip is installed" pip3 --version
# Check that tools can execute
check "autopep8" autopep8 --version
check "black" black --version
check "yapf" yapf --version
check "bandit" bandit --version
check "flake8" flake8 --version
check "mypy" mypy --version
check "pycodestyle" pycodestyle --version
check "pydocstyle" pydocstyle --version
check "pylint" pylint --version
check "pytest" pytest --version
# Check paths in settings
check "current symlink is correct" bash -c "which python | grep /usr/local/python/current/bin/python"
check "current symlink works" /usr/local/python/current/bin/python --version
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
# Check compiled with "--enable-shared" -- python truth is opposite of the shells
# therefore we negate the check to get a '0' exit code when the python
# has been compiled with --enable-shared
check "python enable shared" /usr/local/python/current/bin/python -c 'import sys; import sysconfig; sys.exit(sysconfig.get_config_vars("Py_ENABLE_SHARED") != [1])'
# Report result
reportResults
...@@ -26,6 +26,15 @@ ...@@ -26,6 +26,15 @@
} }
} }
}, },
"install_additional_python_rhel_family": {
"image": "almalinux:8",
"features": {
"python": {
"version": "3.11",
"additionalVersions": "3.8,3.9.13,3.10.5"
}
}
},
"install_jupyterlab": { "install_jupyterlab": {
"image": "mcr.microsoft.com/devcontainers/base:focal", "image": "mcr.microsoft.com/devcontainers/base:focal",
"remoteUser": "vscode", "remoteUser": "vscode",
...@@ -37,6 +46,20 @@ ...@@ -37,6 +46,20 @@
} }
} }
}, },
"install_jupyterlab_rhel_family": {
"image": "almalinux:8",
"remoteUser": "vscode",
"features": {
"common-utils": {
"username": "vscode"
},
"python": {
"version": "latest",
"installJupyterlab": true,
"configureJupyterlabAllowOrigin": "*"
}
}
},
"install_additional_jupyterlab": { "install_additional_jupyterlab": {
"image": "mcr.microsoft.com/devcontainers/base:focal", "image": "mcr.microsoft.com/devcontainers/base:focal",
"remoteUser": "vscode", "remoteUser": "vscode",
...@@ -49,12 +72,39 @@ ...@@ -49,12 +72,39 @@
} }
} }
}, },
"install_os_provided_python": { "install_additional_jupyterlab_rhel_family": {
"image": "almalinux:8",
"remoteUser": "vscode",
"features": {
"common-utils": {
"username": "vscode"
},
"python": {
"version": "latest",
"additionalVersions": "3.9",
"installJupyterlab": true,
"configureJupyterlabAllowOrigin": "*"
}
}
},
"install_os_provided_python_deb": {
"image": "mcr.microsoft.com/devcontainers/base:1-bullseye", "image": "mcr.microsoft.com/devcontainers/base:1-bullseye",
"features": { "features": {
"python": "os-provided" "python": "os-provided"
} }
}, },
"install_os_provided_python_rhel_family": {
"image": "almalinux:8",
"features": {
"python": "os-provided"
}
},
"install_os_provided_python_mariner": {
"image": "mcr.microsoft.com/cbl-mariner/base/core:2.0",
"features": {
"python": "os-provided"
}
},
"install_jupyterlab_from_python_image": { "install_jupyterlab_from_python_image": {
"image": "mcr.microsoft.com/devcontainers/python:3.10-bullseye", "image": "mcr.microsoft.com/devcontainers/python:3.10-bullseye",
"remoteUser": "vscode", "remoteUser": "vscode",
...@@ -99,5 +149,89 @@ ...@@ -99,5 +149,89 @@
"version": "3.12" "version": "3.12"
} }
} }
},
"install_alternate_tools": {
"image": "mcr.microsoft.com/devcontainers/base:1-ubuntu-22.04",
"features": {
"python": {
"version": "3.12",
"toolsToInstall": "ruff,mypy,bandit,pipenv,virtualenv,pytest"
}
}
},
"install_alternate_tools_rhel_family": {
"image": "almalinux:8",
"features": {
"python": {
"version": "3.12",
"toolsToInstall": "ruff,mypy,bandit,pipenv,virtualenv,pytest"
}
}
},
"centos-7": {
"image": "centos:centos7",
"features": {
"python": {
"version": "3.11"
}
}
},
"alma-8": {
"image": "almalinux:8",
"features": {
"python": {
"version": "3.11"
}
}
},
"alma-8-minimal": {
"image": "almalinux:8-minimal",
"features": {
"python": {
"version": "3.11"
}
}
},
"alma-9": {
"image": "almalinux:9",
"features": {
"python": {
"version": "3.11"
}
}
},
"alma-9-minimal": {
"image": "almalinux:9-minimal",
"features": {
"python": {
"version": "3.11"
}
}
},
"fedora": {
"image": "fedora",
"features": {
"python": {
"version": "3.11"
}
}
},
"install_python_shared_lib_deb": {
"image": "ubuntu:focal",
"features": {
"python": {
"version": "3.11",
"enableShared": true
}
}
},
"install_python_shared_lib_rhel_family": {
"image": "almalinux:8",
"features": {
"python": {
"version": "3.11",
"enableShared": true
}
}
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment