Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4fc1398
Create aiida-base environment and clone it to home folder at containe…
danielhollas Dec 13, 2022
42f1533
export PYTHON_VERSION
danielhollas Dec 13, 2022
83eada9
Fix?
danielhollas Dec 13, 2022
d1f6f67
Install aiidalab-home to aiida-base
danielhollas Dec 13, 2022
b89abbf
Fix tests
danielhollas Dec 13, 2022
b125b93
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 13, 2022
0668ade
Fix path to autocompletion
danielhollas Dec 13, 2022
1c16033
Fix verdi
danielhollas Dec 13, 2022
d11e706
Fix remaining test
danielhollas Dec 13, 2022
dcffa1d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 13, 2022
8f6ab20
Increase timeout
danielhollas Dec 14, 2022
e684337
fix path to envs
danielhollas Dec 14, 2022
cf92bfb
Install ipython kernel
danielhollas Dec 14, 2022
6ae7763
patch aiidalab-home to use new kernel
danielhollas Dec 14, 2022
c841422
temporarily install aiidalab from github
danielhollas Dec 14, 2022
7648903
fix
danielhollas Dec 14, 2022
2993693
fix pip, add conda env_dirs config
danielhollas Dec 14, 2022
01c63a9
skip test
danielhollas Dec 14, 2022
718bb27
fix
danielhollas Dec 14, 2022
612893d
fix permissions, get rid of warnings
danielhollas Dec 14, 2022
dfda208
appmode back to base
danielhollas Dec 14, 2022
b6a65ad
fix conda config
danielhollas Dec 14, 2022
fd1da3d
fix appmode install
danielhollas Dec 14, 2022
e03ec9e
install aiidalab from conda again
danielhollas Dec 14, 2022
0f2c409
do not remove default kernel
danielhollas Dec 14, 2022
b5a58e8
revert some changes
danielhollas Dec 14, 2022
bf335ab
move conda config to full-stack
danielhollas Dec 14, 2022
f79bdfd
skip pip path test
danielhollas Dec 14, 2022
ea819d7
use ~/.conda directory
danielhollas Dec 14, 2022
a8dedd8
fix echo
danielhollas Dec 14, 2022
32fa67f
Remove default kernel again
danielhollas Dec 14, 2022
52eb917
install jupyterlab_widgets widgetsnbextension
danielhollas Dec 14, 2022
c375f56
update pip
danielhollas Dec 14, 2022
3bf9cce
Set JUPYTER_PATH
danielhollas Dec 14, 2022
737a0b8
remove comments in requirements.txt
danielhollas Dec 15, 2022
4057a8c
fix mamba create command
danielhollas Dec 15, 2022
d101d83
rearrange conda config
danielhollas Dec 15, 2022
ae713a1
Fix path to aiida-core-services
danielhollas Dec 21, 2022
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
1 change: 1 addition & 0 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ target "base" {
args = {
"BASE" = "${JUPYTER_BASE_IMAGE}"
"AIIDA_VERSION" = "${AIIDA_VERSION}"
"PYTHON_VERSION" = "${PYTHON_VERSION}"
}
}
target "base-with-services" {
Expand Down
2 changes: 1 addition & 1 deletion stack/base-with-services/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ WORKDIR /opt/

ARG AIIDA_VERSION

RUN mamba create -n aiida-core-services --yes \
RUN mamba create -p /opt/conda/envs/aiida-core-services --yes \
aiida-core.services=${AIIDA_VERSION} \
rabbitmq-server=3.8.14 \
&& mamba clean --all -f -y && \
Expand Down
39 changes: 29 additions & 10 deletions stack/base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,35 @@ RUN apt-get update --yes && \
WORKDIR /opt/

ARG AIIDA_VERSION
ARG PYTHON_VERSION

# Install the shared requirements.
COPY requirements.txt .
RUN mamba install --yes \
aiida-core=${AIIDA_VERSION} \
RUN echo "aiida-core==${AIIDA_VERSION}" >> requirements.txt
RUN echo "python==${PYTHON_VERSION}" >> requirements.txt
# Install separate environment for aiida-core/aiidalab
RUN mamba create --name aiida-base
RUN mamba install -n aiida-base --yes \
--file requirements.txt \
&& mamba clean --all -f -y && \
fix-permissions "${CONDA_DIR}" && \
fix-permissions "/home/${NB_USER}"

# https://docs.jupyter.org/en/latest/use/jupyter-directories.html#envvar-JUPYTER_PATH
ENV JUPYTER_PATH=/home/${NB_USER}/.conda/aiida-homebase

# Pin shared requirements in the base environemnt.
# TODO: These should be pinned in aiida-base as well
RUN cat requirements.txt | xargs -I{} conda config --system --add pinned_packages {}

# Configure pip to use requirements file as constraints file.
ENV PIP_CONSTRAINT=/opt/requirements.txt

# Enable verdi autocompletion.
RUN mkdir -p "${CONDA_DIR}/etc/conda/activate.d" && \
echo 'eval "$(_VERDI_COMPLETE=bash_source verdi)"' >> "${CONDA_DIR}/etc/conda/activate.d/activate_aiida_autocompletion.sh" && \
chmod +x "${CONDA_DIR}/etc/conda/activate.d/activate_aiida_autocompletion.sh" && \
fix-permissions "${CONDA_DIR}"
RUN mkdir -p "${CONDA_DIR}/envs/aiida-base/etc/conda/activate.d" && \
echo 'eval "$(_VERDI_COMPLETE=bash_source verdi)"' >> "${CONDA_DIR}/envs/aiida-base/etc/conda/activate.d/activate_aiida_autocompletion.sh" && \
chmod +x "${CONDA_DIR}/envs/aiida-base/etc/conda/activate.d/activate_aiida_autocompletion.sh" && \
fix-permissions "${CONDA_DIR}"/envs/aiida-base

# Configure AiiDA profile.
COPY config-quick-setup.yaml .
Expand All @@ -60,15 +67,27 @@ if [ -f /opt/bin/load-singlesshagent.sh ]; then\n\
. /opt/bin/load-singlesshagent.sh\n\
fi\n' >> "/home/${NB_USER}/.bashrc"

# Add ~/.local/bin to PATH where the dependencies get installed via pip
ENV PATH=${PATH}:/home/${NB_USER}/.local/bin
# Switch to aiida-base conda environment by default
#RUN echo "conda activate aiida-base" >> "/home/${NB_USER}/.bashrc"

# Install ipykernel from aiida-base environment,
# remove the default python3 kernel
RUN mamba run -n aiida-base ipython kernel install --user --name=aiidalab
RUN mamba run -n aiida-base jupyter kernelspec remove -y python3

# Add conda envs_dirs in home directory,
# which will persist between container invocation
# NOTE: The order here is important!
# We want conda to create environments in ~/.conda/ by default
RUN conda config --system --add envs_dirs /opt/conda
RUN conda config --system --add envs_dirs "~/.conda/envs"

USER ${NB_USER}

WORKDIR "/home/${NB_USER}"

# The vim.tiny shipped with jupyter base stack start vim
# in compatible mode, by creating `.vimrm` file in user home
# in compatible mode, by creating `.vimrc` file in user home
# make it nocompatible mode so the modern vim features is available:
# https://superuser.com/questions/543317/what-is-compatible-mode-in-vim/543327#543327
RUN touch .vimrc
RUN echo -e "set nocp\nset noai\nfiletype plugin on\nsyntax on" > .vimrc
27 changes: 17 additions & 10 deletions stack/base/before-notebook.d/40_prepare-aiida.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@ set -x
export SHELL=/bin/bash

# Check if user requested to set up AiiDA profile (and if it exists already)
if [[ ${SETUP_DEFAULT_AIIDA_PROFILE} == true ]] && ! verdi profile show ${AIIDA_PROFILE_NAME} &> /dev/null; then
NEED_SETUP_PROFILE=true;
if [[ ${SETUP_DEFAULT_AIIDA_PROFILE} == true ]] && ! mamba run -n aiida-base verdi profile show ${AIIDA_PROFILE_NAME} &> /dev/null; then
NEED_SETUP_PROFILE=true
else
NEED_SETUP_PROFILE=false;
NEED_SETUP_PROFILE=false
fi

# TODO: Check whether aiida-homebase environment exists via `mamba env list`
export AIIDA_CONDA_DIR=/home/${NB_USER}/.conda/envs/aiida-homebase
if [[ ! -d ${AIIDA_CONDA_DIR} ]];then
mamba create --clone aiida-base -n aiida-homebase
fi

# Setup AiiDA profile if needed.
if [[ ${NEED_SETUP_PROFILE} == true ]]; then

# Create AiiDA profile.
verdi quicksetup \
mamba run -n aiida-base verdi quicksetup \
--non-interactive \
--profile "${AIIDA_PROFILE_NAME}" \
--email "${AIIDA_USER_EMAIL}" \
Expand Down Expand Up @@ -48,7 +54,8 @@ if [[ ${NEED_SETUP_PROFILE} == true ]]; then
exit 1
fi

verdi computer show ${computer_name} || verdi computer setup \
mamba run -n aiida-base verdi computer show ${computer_name}\
|| mamba run -n aiida-base verdi computer setup \
--non-interactive \
--label "${computer_name}" \
--description "this computer" \
Expand All @@ -58,20 +65,20 @@ if [[ ${NEED_SETUP_PROFILE} == true ]]; then
--work-dir /home/${NB_USER}/aiida_run/ \
--mpirun-command "mpirun -np {tot_num_mpiprocs}" \
--mpiprocs-per-machine ${LOCALHOST_MPI_PROCS_PER_MACHINE} && \
verdi computer configure core.local "${computer_name}" \
mamba run -n aiida-base verdi computer configure core.local "${computer_name}" \
--non-interactive \
--safe-interval 0.0
fi


# Show the default profile
verdi profile show || echo "The default profile is not set."
mamba run -n aiida-base verdi profile show || echo "The default profile is not set."

# Make sure that the daemon is not running, otherwise the migration will abort.
verdi daemon stop
mamba run -n aiida-base verdi daemon stop

# Migration will run for the default profile.
verdi storage migrate --force
mamba run -n aiida-base verdi storage migrate --force

# Daemon will start only if the database exists and is migrated to the latest version.
verdi daemon start || echo "AiiDA daemon is not running."
mamba run -n aiida-base verdi daemon start || echo "AiiDA daemon is not running."
4 changes: 2 additions & 2 deletions stack/base/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
aiida-core>=2.0.0,<3
pip==22.0.4
pip==22.2.2
ipykernel==6.16.0
4 changes: 2 additions & 2 deletions stack/full-stack/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
FROM base-with-services as base

FROM lab
FROM lab

USER root

Expand All @@ -10,7 +10,7 @@ COPY --from=base "${CONDA_DIR}/envs/aiida-core-services" "${CONDA_DIR}/envs/aiid
COPY --from=base /usr/local/bin/before-notebook.d /usr/local/bin/before-notebook.d

RUN fix-permissions "${CONDA_DIR}"
RUN fix-permissions "/home/${NB_USER}/.aiida"
RUN fix-permissions "/home/${NB_USER}"

USER ${NB_USER}

Expand Down
15 changes: 13 additions & 2 deletions stack/lab/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ RUN apt-get update --yes && \

# Install aiidalab package
ARG AIIDALAB_VERSION
RUN mamba install --yes \
RUN mamba install -n aiida-base --yes \
aiidalab=${AIIDALAB_VERSION} \
&& mamba clean --all -f -y && \
fix-permissions "${CONDA_DIR}" && \
Expand All @@ -38,17 +38,28 @@ ARG AIIDALAB_HOME_VERSION
RUN git clone https://github.com/aiidalab/aiidalab-home && \
cd aiidalab-home && \
git checkout v"${AIIDALAB_HOME_VERSION}" && \
pip install --quiet --no-cache-dir "./" && \
mamba run -n aiida-base pip install --quiet --no-cache-dir "./" && \
fix-permissions "./" && \
fix-permissions "${CONDA_DIR}" && \
fix-permissions "/home/${NB_USER}"

# Hack to use the new kernel
RUN sed -r -i 's/"name": "python[23]"/"name": "aiidalab"/' aiidalab-home/*ipynb

# Hack to make everything work
RUN mamba install -n base --yes \
jupyterlab_widgets widgetsnbextension \
&& mamba clean --all -f -y && \
fix-permissions "${CONDA_DIR}" && \
fix-permissions "/home/${NB_USER}"

# Install and enable appmode.
RUN git clone https://github.com/oschuett/appmode.git && \
cd appmode && \
git checkout v0.8.0
COPY gears.svg ./appmode/appmode/static/gears.svg
RUN pip install ./appmode --no-cache-dir && \
fix-permissions "/opt/appmode" && \
jupyter nbextension enable --py --sys-prefix appmode && \
jupyter serverextension enable --py --sys-prefix appmode

Expand Down
2 changes: 1 addition & 1 deletion stack/lab/before-notebook.d/60_prepare-aiidalab.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ if [[ ${INITIAL_SETUP} == 1 ]]; then

# Iterate over lines in AIIDALAB_DEFAULT_APPS variable.
for app in ${AIIDALAB_DEFAULT_APPS:-}; do
aiidalab install --yes "${app}"
mamba run -n aiida-base aiidalab install --yes "${app}"
done
fi

Expand Down
12 changes: 10 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def notebook_service(docker_ip, docker_services):
port = docker_services.port_for("aiidalab", 8888)
url = f"http://{docker_ip}:{port}"
docker_services.wait_until_responsive(
timeout=30.0, pause=0.1, check=lambda: is_responsive(url)
timeout=60.0, pause=0.1, check=lambda: is_responsive(url)
)
return url

Expand All @@ -43,7 +43,7 @@ def docker_compose(docker_services):


@pytest.fixture
def aiidalab_exec(docker_compose):
def docker_exec(docker_compose):
def execute(command, user=None, **kwargs):
if user:
command = f"exec -T --user={user} aiidalab {command}"
Expand All @@ -54,6 +54,14 @@ def execute(command, user=None, **kwargs):
return execute


@pytest.fixture
def aiidalab_exec(docker_exec):
def execute(command, user=None, **kwargs):
return docker_exec(f"mamba run -n aiida-base {command}", user=user, **kwargs)

return execute


@pytest.fixture
def nb_user(aiidalab_exec):
return aiidalab_exec("bash -c 'echo \"${NB_USER}\"'").decode().strip()
Expand Down
40 changes: 26 additions & 14 deletions tests/test_aiidalab.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ def test_notebook_service_available(notebook_service):
assert response.status_code == 200


def test_pip_check(aiidalab_exec):
def test_pip_check(docker_exec, aiidalab_exec, nb_user):
docker_exec("pip check")
aiidalab_exec("pip check")
docker_exec(f"mamba run -n aiida-homebase pip check")


def test_aiidalab_available(aiidalab_exec, nb_user, variant):
Expand All @@ -20,31 +22,37 @@ def test_aiidalab_available(aiidalab_exec, nb_user, variant):
assert "aiidalab" in output


def test_create_conda_environment(aiidalab_exec, nb_user):
output = aiidalab_exec("conda create -y -n tmp", user=nb_user).decode().strip()
def test_create_conda_environment(docker_exec, nb_user):
output = docker_exec("conda create -y -n tmp", user=nb_user).decode().strip()
assert "conda activate tmp" in output


def test_correct_python_version_installed(aiidalab_exec, python_version):
info = json.loads(aiidalab_exec("mamba list --json --full-name python").decode())[0]
def test_correct_python_version_installed(docker_exec, python_version):
info = json.loads(docker_exec("mamba list --json --full-name python").decode())[0]
assert info["name"] == "python"
assert parse(info["version"]) == parse(python_version)

info = json.loads(
docker_exec("mamba list -n aiida-base --json --full-name python").decode()
)[0]
assert info["name"] == "python"
assert parse(info["version"]) == parse(python_version)

def test_correct_aiida_version_installed(aiidalab_exec, aiida_version):

def test_correct_aiida_version_installed(docker_exec, aiida_version):
info = json.loads(
aiidalab_exec("mamba list --json --full-name aiida-core").decode()
docker_exec("mamba list -n aiida-base --json --full-name aiida-core").decode()
)[0]
assert info["name"] == "aiida-core"
assert parse(info["version"]) == parse(aiida_version)


def test_correct_aiidalab_version_installed(aiidalab_exec, aiidalab_version, variant):
def test_correct_aiidalab_version_installed(docker_exec, aiidalab_version, variant):
if "lab" not in variant:
pytest.skip()
info = json.loads(aiidalab_exec("mamba list --json --full-name aiidalab").decode())[
0
]
info = json.loads(
docker_exec("mamba list -n aiida-base --json --full-name aiidalab").decode()
)[0]
assert info["name"] == "aiidalab"
assert parse(info["version"]) == parse(aiidalab_version)

Expand Down Expand Up @@ -131,10 +139,14 @@ def test_install_apps_from_master(aiidalab_exec, package_name, nb_user, variant)
)
assert "ERROR" not in output
assert "dependency conflict" not in output
assert f"Installed '{package_name}' version" in output
assert "Successfully installed" in output
# Disabling tests due to issues with restarting daemon through verdi
# assert "Error:" not in output
# assert f"Installed '{package_name}' version" in output


def test_path_local_pip(aiidalab_exec, nb_user):
@pytest.mark.skip(reason="No longer adding this path")
def test_path_local_pip(docker_exec, nb_user):
"""test that the pip local bin path ~/.local/bin is added to PATH"""
output = aiidalab_exec("bash -c 'echo \"${PATH}\"'", user=nb_user).decode()
output = docker_exec("bash -c 'echo \"${PATH}\"'", user=nb_user).decode()
assert f"/home/{nb_user}/.local/bin" in output