diff --git a/docs/index.rst b/docs/index.rst index 64ee031..605b73b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -56,6 +56,7 @@ Topic guides provide in-depth explanations of specific topics. guides/requirements guides/admin topic/security + topic/customizing-installer Troubleshooting diff --git a/tests/test_conda.py b/tests/test_conda.py index a5a84e0..7b372e5 100644 --- a/tests/test_conda.py +++ b/tests/test_conda.py @@ -66,3 +66,21 @@ def test_ensure_pip_packages(prefix): '-c', 'import numpy' ]) + + +def test_ensure_pip_requirements(prefix): + """ + Test installing pip packages with requirements.txt in conda environment + """ + conda.ensure_conda_env(prefix) + conda.ensure_conda_packages(prefix, ['pip']) + with tempfile.NamedTemporaryFile() as f: + # Sample small package to test + f.write('there'.encode()) + f.flush() + conda.ensure_pip_requirements(prefix, f.name) + subprocess.check_call([ + os.path.join(prefix, 'bin', 'python'), + '-c', + 'import there' + ]) diff --git a/tljh/conda.py b/tljh/conda.py index 994bc79..d7dab54 100644 --- a/tljh/conda.py +++ b/tljh/conda.py @@ -66,3 +66,19 @@ def ensure_pip_packages(prefix, packages): 'install', '--no-cache-dir', ] + packages) + + +def ensure_pip_requirements(prefix, requirements_path): + """ + Ensure pip packages from given requirements_path are installed in given conda prefix. + + requirements_path can be a file or a URL. + """ + abspath = os.path.abspath(prefix) + pip_executable = [os.path.join(abspath, 'bin', 'python'), '-m', 'pip'] + + subprocess.check_output(pip_executable + [ + 'install', + '-r', + requirements_path + ]) diff --git a/tljh/installer.py b/tljh/installer.py index 39e7fb7..9253612 100644 --- a/tljh/installer.py +++ b/tljh/installer.py @@ -96,7 +96,7 @@ def ensure_usergroups(): f.write('Defaults exempt_group = jupyterhub-admins\n') -def ensure_user_environment(): +def ensure_user_environment(user_requirements_txt_file): """ Set up user conda environment with required packages """ @@ -116,6 +116,10 @@ def ensure_user_environment(): 'nteract-on-jupyter==1.8.1' ]) + if user_requirements_txt_file: + # FIXME: This currently fails hard, should fail soft and not abort installer + conda.ensure_pip_requirements(USER_ENV_PREFIX, user_requirements_txt_file) + def ensure_admins(admins): """ @@ -175,13 +179,17 @@ def main(): nargs='*', help='List of usernames set to be admin' ) + argparser.add_argument( + '--user-requirements-txt-url', + help='URL to a requirements.txt file that should be installed in the user enviornment' + ) args = argparser.parse_args() ensure_admins(args.admin) ensure_usergroups() - ensure_user_environment() + ensure_user_environment(args.user_requirements_txt_url) print("Setting up JupyterHub...") ensure_jupyterhub_package(HUB_ENV_PREFIX)