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:
parent
b947d0ed35
commit
e99bc62ea3
10 changed files with 128 additions and 168 deletions
1
.github/workflows/test-all.yaml
vendored
1
.github/workflows/test-all.yaml
vendored
|
@ -27,7 +27,6 @@ jobs:
|
|||
"go",
|
||||
"hugo",
|
||||
"java",
|
||||
"python jupyterlab", # Install 'python', then 'jupyterlab'
|
||||
"kubectl-helm-minikube",
|
||||
"node",
|
||||
"oryx",
|
||||
|
|
1
.github/workflows/test-pr.yaml
vendored
1
.github/workflows/test-pr.yaml
vendored
|
@ -27,7 +27,6 @@ jobs:
|
|||
go: ./**/go/**
|
||||
hugo: ./**/hugo/**
|
||||
java: ./**/java/**
|
||||
'python jupyterlab': ./**/jupyterlab/**
|
||||
kubectl-helm-minikube: ./**/kubectl-helm-minikube/**
|
||||
node: ./**/node/**
|
||||
oryx: ./**/oryx/**
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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": {
|
||||
|
|
|
@ -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,12 +359,9 @@ 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}"
|
||||
|
||||
|
@ -352,31 +378,43 @@ 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
|
||||
"${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=""
|
||||
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_path="/tmp/pip-tmp/bin/"
|
||||
PIPX_DIR="/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}
|
||||
"${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 "$(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
|
||||
)"
|
||||
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!"
|
||||
|
|
12
test-scenarios/install_jupyterlab.sh
Normal file
12
test-scenarios/install_jupyterlab.sh
Normal 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
|
|
@ -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": "*"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue