Merge JupyterLab feature into Python feature (#40)

* Restructure tools installation

* Tweak bash and zsh config

* Remove extra space

* Update comments

* Add option to install JupyterLab

* Add option to configure JupyterLab

* Add option to install ML packages

* Remove deprecated JuptyerLab feature

* Add new arguments to Python feature

* Remove trailing whitespace

* Organize new arguments

* Resolve feedback

* Create new scenario for JupyterLab

* Fix user in JupyterLab scenario

* Revert changes to Python test

* Remove ML packages

* Update test names

* Rename CORS option
This commit is contained in:
JP Ungaretti 2022-06-08 11:19:31 -07:00 committed by GitHub
parent b947d0ed35
commit e99bc62ea3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 128 additions and 168 deletions

View file

@ -27,7 +27,6 @@ jobs:
"go",
"hugo",
"java",
"python jupyterlab", # Install 'python', then 'jupyterlab'
"kubectl-helm-minikube",
"node",
"oryx",

View file

@ -27,7 +27,6 @@ jobs:
go: ./**/go/**
hugo: ./**/hugo/**
java: ./**/java/**
'python jupyterlab': ./**/jupyterlab/**
kubectl-helm-minikube: ./**/kubectl-helm-minikube/**
node: ./**/node/**
oryx: ./**/oryx/**

View file

@ -1,33 +0,0 @@
{
"id": "jupyterlab",
"name": "Jupyter Lab",
"options": {
"version": {
"type": "string",
"proposals": [
"latest",
"3.6.2"
],
"default": "latest",
"description": "Select or enter a jupyterlab version."
},
"python_binary": {
"type": "string",
"proposals": [
"python",
"/usr/local/python/bin/python"
],
"default": "python",
"description": "Select or enter the python binary path."
}
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-toolsai.jupyter"
],
"install": {
"app": "",
"file": "install.sh"
}
}

View file

@ -1,71 +0,0 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/jupyterlab.md
# Maintainer: The VS Code and Codespaces Teams
set -ex
VERSION=${VERSION:-"latest"}
PYTHON=${PYTHON_BINARY:-"python"}
USERNAME=${USERNAME:-"automatic"}
ALLOW_ALL_ORIGINS=${ALLOW_ALL_ORIGINS:-""}
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
# If in automatic mode, determine if a user already exists, if not use vscode
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=vscode
fi
elif [ "${USERNAME}" = "none" ]; then
USERNAME=root
USER_UID=0
USER_GID=0
fi
addToJupyterConfig() {
JUPYTER_DIR="/home/${USERNAME}/.jupyter"
JUPYTER_CONFIG="${JUPYTER_DIR}/jupyter_notebook_config.py"
# Make sure the config file exists
test -d ${JUPYTER_DIR} || mkdir ${JUPYTER_DIR}
test -f ${JUPYTER_CONFIG} || touch ${JUPYTER_CONFIG}
# Don't write the same line more than once
grep -q ${1} ${JUPYTER_CONFIG} || echo ${1} >> ${JUPYTER_CONFIG}
}
# Make sure that Python is available
if ! ${PYTHON} --version > /dev/null ; then
echo "You need to install Python before installing JupyterLab."
exit 1
fi
# pip skips installation if JupyterLab is already installed
echo "Installing JupyterLab..."
if [ "${VERSION}" = "latest" ]; then
${PYTHON} -m pip install jupyterlab --no-cache-dir
else
${PYTHON} -m pip install jupyterlab=="${VERSION}" --no-cache-dir
fi
if [ "${ALLOW_ALL_ORIGINS}" = 'true' ]; then
addToJupyterConfig "c.ServerApp.allow_origin = '*'"
addToJupyterConfig "c.NotebookApp.allow_origin = '*'"
fi

View file

@ -37,6 +37,16 @@
"type": "boolean",
"default": "true",
"description": "If true, overrides existing version (if any) of python on the PATH"
},
"install_jupyterlab": {
"type": "boolean",
"default": false,
"description": "Install JupyterLab, a web-based interactive development environment for notebooks"
},
"configure_jupyterlab_allow_origin": {
"type": "string",
"default": "",
"description": "Configure JupyterLab to accept HTTP requests from the specified origin"
}
},
"containerEnv": {

View file

@ -19,6 +19,9 @@ USERNAME=${USERNAME:-"automatic"}
UPDATE_RC=${UPDATE_RC:-"true"}
USE_ORYX_IF_AVAILABLE=${USE_ORYX_IF_AVAILABLE:-"true"}
INSTALL_JUPYTERLAB=${INSTALL_JUPYTERLAB:-"false"}
CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN=${CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN:-""}
DEFAULT_UTILS=("pylint" "flake8" "autopep8" "black" "yapf" "mypy" "pydocstyle" "pycodestyle" "bandit" "pipenv" "virtualenv")
PYTHON_SOURCE_GPG_KEYS="64E628F8D684696D B26995E310250568 2D347EA6AA65421D FB9921286F5E1540 3A5CA953F73C700D 04C367C218ADD4FF 0EDDC5F26A45C816 6AF053F07D9DC8D2 C9BE28DEE6DF025C 126EB563A74B06BF D9866941EA5BBD71 ED9D77D5"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
@ -301,6 +304,32 @@ install_using_oryx() {
add_symlink
}
sudo_if() {
COMMAND="$*"
if [ "$(id -u)" -eq 0 ] && [ "$USERNAME" != "root" ]; then
su - "$USERNAME" -c "$COMMAND"
else
"$COMMAND"
fi
}
install_user_package() {
PACKAGE="$1"
sudo_if "$INSTALL_PATH/bin/python3" -m pip install --user --upgrade --no-cache-dir "$PACKAGE"
}
add_user_jupyter_config() {
CONFIG_DIR="/home/$USERNAME/.jupyter"
CONFIG_FILE="$CONFIG_DIR/jupyter_notebook_config.py"
# Make sure the config file exists or create it with proper permissions
test -d "$CONFIG_DIR" || sudo_if mkdir "$CONFIG_DIR"
test -f "$CONFIG_FILE" || sudo_if touch "$CONFIG_FILE"
# Don't write the same config more than once
grep -q "$1" "$CONFIG_FILE" || echo "$1" >> "$CONFIG_FILE"
}
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
@ -310,7 +339,7 @@ check_packages curl ca-certificates gnupg2 tar make gcc libssl-dev zlib1g-dev li
libxmlsec1-dev libsqlite3-dev libffi-dev liblzma-dev uuid-dev
# Install python from source if needed
# Install Python from source if needed
if [ "${PYTHON_VERSION}" != "none" ]; then
CURRENT_PATH="${PYTHON_INSTALL_PATH}/current"
# If the os-provided versions are "good enough", detect that and bail out.
@ -330,53 +359,62 @@ if [ "${PYTHON_VERSION}" != "none" ]; then
updaterc "if [[ \"\${PATH}\" != *\"${CURRENT_PATH}/bin\"* ]]; then export PATH=${CURRENT_PATH}/bin:\${PATH}; fi"
fi
# If not installing python tools, exit
if [ "${INSTALL_PYTHON_TOOLS}" != "true" ]; then
echo "Done!"
exit 0
fi
# Install Python tools if needed
if [ "${INSTALL_PYTHON_TOOLS}" = "true" ]; then
echo 'Installing Python tools...'
export PIPX_BIN_DIR="${PIPX_HOME}/bin"
export PATH="${CURRENT_PATH}/bin:${PIPX_BIN_DIR}:${PATH}"
export PIPX_BIN_DIR="${PIPX_HOME}/bin"
export PATH="${CURRENT_PATH}/bin:${PIPX_BIN_DIR}:${PATH}"
# Create pipx group, dir, and set sticky bit
if ! cat /etc/group | grep -e "^pipx:" > /dev/null 2>&1; then
groupadd -r pipx
fi
usermod -a -G pipx ${USERNAME}
umask 0002
mkdir -p ${PIPX_BIN_DIR}
chown :pipx ${PIPX_HOME} ${PIPX_BIN_DIR}
chmod g+s ${PIPX_HOME} ${PIPX_BIN_DIR}
# Update pip if not using os provided python
if [ ${PYTHON_VERSION} != "os-provided" ] && [ ${PYTHON_VERSION} != "system" ] && [ ${PYTHON_VERSION} != "none" ]; then
echo "Updating pip..."
${INSTALL_PATH}/bin/python3 -m pip install --no-cache-dir --upgrade pip
fi
# Install tools
echo "Installing Python tools..."
export PYTHONUSERBASE=/tmp/pip-tmp
export PIP_CACHE_DIR=/tmp/pip-tmp/cache
pipx_path=""
if ! type pipx > /dev/null 2>&1; then
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_path="/tmp/pip-tmp/bin/"
fi
for util in "${DEFAULT_UTILS[@]}"; do
if ! type ${util} > /dev/null 2>&1; then
${pipx_path}pipx install --system-site-packages --pip-args '--no-cache-dir --force-reinstall' ${util}
else
echo "${util} already installed. Skipping."
# Create pipx group, dir, and set sticky bit
if ! cat /etc/group | grep -e "^pipx:" > /dev/null 2>&1; then
groupadd -r pipx
fi
done
rm -rf /tmp/pip-tmp
usermod -a -G pipx ${USERNAME}
umask 0002
mkdir -p ${PIPX_BIN_DIR}
chown :pipx ${PIPX_HOME} ${PIPX_BIN_DIR}
chmod g+s ${PIPX_HOME} ${PIPX_BIN_DIR}
updaterc "$(cat << EOF
export PIPX_HOME="${PIPX_HOME}"
export PIPX_BIN_DIR="${PIPX_BIN_DIR}"
if [[ "\${PATH}" != *"\${PIPX_BIN_DIR}"* ]]; then export PATH="\${PATH}:\${PIPX_BIN_DIR}"; fi
EOF
)"
# Update pip if not using os provided python
if [ ${PYTHON_VERSION} != "os-provided" ] && [ ${PYTHON_VERSION} != "system" ] && [ ${PYTHON_VERSION} != "none" ]; then
echo "Updating pip..."
"${INSTALL_PATH}/bin/python3" -m pip install --no-cache-dir --upgrade pip
fi
# Install tools
echo "Installing Python tools..."
export PYTHONUSERBASE=/tmp/pip-tmp
export PIP_CACHE_DIR=/tmp/pip-tmp/cache
PIPX_DIR=""
if ! type pipx > /dev/null 2>&1; then
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
for util in "${DEFAULT_UTILS[@]}"; do
if ! type ${util} > /dev/null 2>&1; then
"${PIPX_DIR}/pipx" install --system-site-packages --pip-args '--no-cache-dir --force-reinstall' ${util}
else
echo "${util} already installed. Skipping."
fi
done
rm -rf /tmp/pip-tmp
updaterc "export PIPX_HOME=\"${PIPX_HOME}\""
updaterc "export PIPX_BIN_DIR=\"${PIPX_BIN_DIR}\""
updaterc "if [[ \"\${PATH}\" != *\"\${PIPX_BIN_DIR}\"* ]]; then export PATH=\"\${PATH}:\${PIPX_BIN_DIR}\"; fi"
fi
# Install JupyterLab if needed
if [ "${INSTALL_JUPYTERLAB}" = "true" ]; then
install_user_package jupyterlab
# Configure JupyterLab if needed
# TODO: True if it's not empty
if [ -n "${CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN}" ]; then
add_user_jupyter_config "c.ServerApp.allow_origin = '${CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN}'"
add_user_jupyter_config "c.NotebookApp.allow_origin = '${CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN}'"
fi
fi
echo "Done!"

View file

@ -0,0 +1,12 @@
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
check "version" jupyter lab --version
check "config" grep ".*.allow_origin = '*'" /home/vscode/.jupyter/jupyter_notebook_config.py
# Report result
reportResults

View file

@ -16,5 +16,24 @@
}
}
]
},
"install_jupyterlab": {
"image": "mcr.microsoft.com/vscode/devcontainers/base:focal",
"remoteUser": "vscode",
"features": [
{
"id": "common",
"options": {
"username": "vscode"
}
},
{
"id": "python",
"options": {
"install_jupyterlab": true,
"configure_jupyterlab_allow_origin": "*"
}
}
]
}
}

View file

@ -1,12 +0,0 @@
#!/bin/bash
set -e
# Optional: Import test library
source dev-container-features-test-lib
# Definition specific tests
check "version" jupyter --version
# Report result
reportResults

View file

@ -10,7 +10,7 @@ _BUILD_ARG_AWS_CLI="./aws-cli/install.sh ${_B
_BUILD_ARG_AZURE_CLI="./az-cli/install.sh ${_BUILD_ARG_AZURE_CLI_VERSION:-latest}"
_BUILD_ARG_SSHD="./sshd/install.sh"
_BUILD_ARG_NODE="./node/install.sh ${_BUILD_ARG_NODE_NVMINSTALLPATH:-/usr/local/share/nvm} ${_BUILD_ARG_NODE_VERSION:-lts/*} automatic true ${_BUILD_ARG_NODE_NODEGYPDEPENDENCIES:-true}"
_BUILD_ARG_PYTHON="./python/install.sh ${_BUILD_ARG_PYTHON_VERSION:-latest} ${_BUILD_ARG_PYTHON_INSTALLPATH:-/usr/local/python} /usr/local/py-utils automatic true ${_BUILD_ARG_PYTHON_INSTALLTOOLS:-true} true ${_BUILD_ARG_PYTHON_OPTIMIZE:-false} ${_BUILD_ARG_PYTHON_OVERRIDEDEFAULTVERSION:-true}"
_BUILD_ARG_PYTHON="./python/install.sh ${_BUILD_ARG_PYTHON_VERSION:-latest} ${_BUILD_ARG_PYTHON_INSTALLPATH:-/usr/local/python} /usr/local/py-utils automatic true ${_BUILD_ARG_PYTHON_INSTALLTOOLS:-true} true ${_BUILD_ARG_PYTHON_OPTIMIZE:-false} ${_BUILD_ARG_PYTHON_OVERRIDEDEFAULTVERSION:-true} ${_BUILD_ARG_PYTHON_INSTALLJUPYTERLAB:-false} ${_BUILD_ARG_PYTHON_CONFIGUREJUPYTERLABALLOWORIGIN:-''}"
_BUILD_ARG_GO="./go/install.sh ${_BUILD_ARG_GOLANG_VERSION:-latest}"
_BUILD_ARG_JAVA="./java/wrapper.sh ${_BUILD_ARG_JAVA_VERSION:-latest}"
_BUILD_ARG_GRADLE="./gradle/install.sh ${_BUILD_ARG_GRADLE_VERSION:-latest}"
@ -20,7 +20,6 @@ _BUILD_ARG_RUST="./rust/install.sh /usr
_BUILD_ARG_POWERSHELL="./powershell/install.sh ${_BUILD_ARG_POWERSHELL_VERSION:-latest}"
_BUILD_ARG_DESKTOP_LITE="./desktop-lite/install.sh automatic ${_BUILD_ARG_DESKTOP_LITE_PASSWORD:-vscode} true ${_BUILD_ARG_DESKTOP_LITE_VNCPORT:-5901} ${_BUILD_ARG_DESKTOP_LITE_WEBPORT:-6080}"
_BUILD_ARG_DOTNET="./dotnet/install.sh ${_BUILD_ARG_DOTNET_VERSION:-latest} ${_BUILD_ARG_DOTNET_RUNTIMEONLY:-false} automatic true /usr/local/dotnet dotnet ${_BUILD_ARG_DOTNET_OVERRIDEDEFAULTVERSION:-true} ${_BUILD_ARG_DOTNET_INSTALLUSINGAPT:-true}"
_BUILD_ARG_JUPYTERLAB="./jupyterlab/install.sh ${_BUILD_ARG_JUPYTERLAB_VERSION:-latest} automatic ${_BUILD_ARG_JUPYTERLAB_PYTHONBINARY:-python} true"
_BUILD_ARG_PHP="./php/install.sh ${_BUILD_ARG_PHP_VERSION:-latest} /usr/local/php ${_BUILD_ARG_PHP_INSTALLCOMPOSER:-true} automatic true ${_BUILD_ARG_PHP_OVERRIDEDEFAULTVERSION:-true}"
_BUILD_ARG_ORYX="./oryx/install.sh automatic true"
_BUILD_ARG_HUGO="./hugo/install.sh ${_BUILD_ARG_HUGO_VERSION:-latest} automatic true"