Skip to content

Commit b026072

Browse files
blairdrummondca-scribner
andauthoredMay 18, 2021
feat: move remote desktop to nginx (#250)
Also: * Add `dev` endpoint to Makefile and NB_PREFIX to tests * Increase connection retries in test suite to give vnc time to start * Add clickable link to `make/dev` output Co-authored-by: Andrew Scribner <[email protected]>
1 parent f25cad4 commit b026072

20 files changed

+738
-62
lines changed
 

Diff for: ‎Makefile

+24-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#
77
# Management of build, pull/push, and testing is modified from
88
# https://github.com/jupyter/docker-stacks
9+
#
10+
# Tests/some elements of makefile strongly inspired by
11+
# https://github.com/jupyter/docker-stacks/blob/master/Makefile
912

1013
# The docker-stacks tag
1114
DOCKER-STACKS-UPSTREAM-TAG := 512afd49b925
@@ -39,7 +42,7 @@ BRANCH_NAME := $(shell ./make_helpers/get_branch_name.sh)
3942

4043
# Other
4144
DEFAULT_PORT := 8888
42-
45+
DEFAULT_NB_PREFIX := /notebook/username/notebookname
4346

4447
.PHONY: clean .output generate-dockerfiles
4548

@@ -222,6 +225,7 @@ install-python-dev-venv:
222225

223226
test/%: REPO?=$(DEFAULT_REPO)
224227
test/%: TAG?=$(DEFAULT_TAG)
228+
test/%: NB_PREFIX?=$(DEFAULT_NB_PREFIX)
225229
test/%: check-test-prereqs # Run all generic and image-specific tests against an image
226230
# End repo with exactly one trailing slash, unless it is empty
227231
REPO=$$(echo "$(REPO)" | sed 's:/*$$:/:' | sed 's:^\s*/*\s*$$::') ;\
@@ -234,4 +238,22 @@ test/%: check-test-prereqs # Run all generic and image-specific tests against an
234238
echo "Found specific tests folder";\
235239
fi;\
236240
echo "Running tests on folders '$${TESTS}'";\
237-
IMAGE_NAME="$${REPO}$(notdir $@):$(TAG)" $(PYTHON) -m pytest -m "not info" $${TESTS}
241+
IMAGE_NAME="$${REPO}$(notdir $@):$(TAG)" NB_PREFIX=$(DEFAULT_NB_PREFIX) $(PYTHON) -m pytest -m "not info" $${TESTS}
242+
243+
dev/%: ARGS?=
244+
dev/%: DARGS?=
245+
dev/%: NB_PREFIX?=$(DEFAULT_NB_PREFIX)
246+
dev/%: PORT?=8888
247+
dev/%: REPO?=$(DEFAULT_REPO)
248+
dev/%: TAG?=$(DEFAULT_TAG)
249+
dev/%: ## run a foreground container for a stack (useful for local testing)
250+
# End repo with exactly one trailing slash, unless it is empty
251+
REPO=$$(echo "$(REPO)" | sed 's:/*$$:/:' | sed 's:^\s*/*\s*$$::') ;\
252+
IMAGE_NAME="$${REPO}$(notdir $@):$(TAG)" ;\
253+
echo "\n###############\nLaunching docker container. Connect to it via http://localhost:$(PORT)$(NB_PREFIX)\n###############\n" ;\
254+
if xdg-open --version > /dev/null; then\
255+
( sleep 5 && xdg-open "http://localhost:8888$(NB_PREFIX)" ) & \
256+
else\
257+
( sleep 5 && open "http://localhost:8888$(NB_PREFIX)" ) & \
258+
fi; \
259+
docker run -it --rm -p $(PORT):8888 -e NB_PREFIX=$(NB_PREFIX) $(DARGS) $${IMAGE_NAME} $(ARGS)

Diff for: ‎README.md

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ For example: `k8scc01covidacr.azurecr.io/IMAGENAME:BRANCH_NAME`.
3737

3838
### Testing images
3939

40+
#### Running and Connecting to Images Locally/Interactively
41+
42+
To test an image interactively, use `make dev/IMAGENAME`. This `docker run`'s a built image, automatically forwarding ports to your local machine and providing a link to connect to.
43+
44+
#### Automated Testing
45+
4046
Automated tests are included for the generated Docker images using `pytest`. This testing suite is modified from the [docker-stacks](https://github.com/jupyter/docker-stacks) test suite. Image testing is invoked through `make test/IMAGENAME` (with optional `REPO` and `TAG` arguments like `make build`).
4147

4248
Testing of a given image consists of general and image-specific tests:

Diff for: ‎conftest.py

+26-5
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212

1313
LOGGER = logging.getLogger(__name__)
1414

15-
IMAGE_NAME_ENV_VAR="IMAGE_NAME"
15+
IMAGE_NAME_ENV_VAR = "IMAGE_NAME"
16+
NB_PREFIX_ENV_VAR = "NB_PREFIX"
17+
1618

1719
@pytest.fixture(scope='session')
1820
def http_client():
1921
"""Requests session with retries and backoff."""
2022
s = requests.Session()
21-
retries = Retry(total=6, backoff_factor=1)
23+
retries = Retry(total=9, backoff_factor=1)
2224
s.mount('http://', HTTPAdapter(max_retries=retries))
2325
s.mount('https://', HTTPAdapter(max_retries=retries))
2426
return s
@@ -36,10 +38,26 @@ def image_name():
3638
image_name = os.getenv(IMAGE_NAME_ENV_VAR)
3739
LOGGER.debug(f"Found image_name {image_name} in env variable {IMAGE_NAME_ENV_VAR}")
3840
if image_name is None or len(image_name) == 0:
39-
raise ValueError(f"Image name not found in environment variable {IMAGE_NAME_ENV_VAR}. Did you forget to set it?")
41+
raise ValueError(f"Image name not found in environment variable {IMAGE_NAME_ENV_VAR}. Did you forget to set it?")
4042
return image_name
4143

4244

45+
@pytest.fixture(scope='session')
46+
def nb_prefix():
47+
"""
48+
NB_PREFIX environment variable for test
49+
50+
Used in the notebook redirect path (eg: localhost:8888/$NB_PREFIX)
51+
"""
52+
nb_prefix = os.getenv(NB_PREFIX_ENV_VAR)
53+
LOGGER.debug(f"Found nb_prefix {nb_prefix} in env variable {NB_PREFIX_ENV_VAR}")
54+
if nb_prefix is None or len(nb_prefix) == 0:
55+
LOGGER.debug(f"nb_prefix not found in environment variable {NB_PREFIX_ENV_VAR}. Did you forget to set it?"
56+
f" Setting to empty string")
57+
nb_prefix = ""
58+
return nb_prefix
59+
60+
4361
class TrackedContainer(object):
4462
"""Wrapper that collects docker container configuration and delays
4563
container creation/execution.
@@ -50,6 +68,8 @@ class TrackedContainer(object):
5068
Docker client instance
5169
image_name: str
5270
Name of the docker image to launch
71+
nb_prefix: str, optional
72+
The NB_PREFIX arg, the base url for the server
5373
**kwargs: dict, optional
5474
Default keyword arguments to pass to docker.DockerClient.containers.run
5575
"""
@@ -96,7 +116,7 @@ def get_cmd(self):
96116

97117

98118
@pytest.fixture(scope='function')
99-
def container(docker_client, image_name):
119+
def container(docker_client, image_name, nb_prefix):
100120
"""Notebook container with initial configuration appropriate for testing
101121
(e.g., HTTP port exposed to the host for HTTP calls).
102122
@@ -108,7 +128,8 @@ def container(docker_client, image_name):
108128
detach=True,
109129
ports={
110130
'8888/tcp': 8888
111-
}
131+
},
132+
environment={'NB_PREFIX': nb_prefix},
112133
)
113134
yield container
114135
container.remove()

Diff for: ‎docker-bits/0_Rocker.Dockerfile

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# Rocker/geospatial is tagged by R version number. They are not clear on whether they'll change those tagged
1+
# Rocker/geospatial is tagged by R version number. They are not clear on whether they'll change those tagged
22
# images for hotfixes, so always pin tag and digest to prevent unexpected upstream changes
33
FROM rocker/geospatial:4.0.3@sha256:9e00ab4fec7b38a0edbadb07e7554bf3b7fa34d15c6fe42522a09ae88d336219
44

55
# For compatibility with docker stacks
66
ARG NB_USER="jovyan"
77
ARG HOME=/home/$NB_USER
8-
ARG NB_UID="1000"
9-
ARG NB_GID="100"
8+
ENV NB_UID="1000"
9+
ENV NB_GID="100"
1010

1111
USER root
1212
ENV PATH="/home/jovyan/.local/bin/:${PATH}"
@@ -18,3 +18,6 @@ RUN apt-get update --yes \
1818
RUN /rocker_scripts/install_shiny_server.sh \
1919
&& pip3 install jupyter \
2020
&& rm -rf /var/lib/apt/lists/*
21+
22+
# Users should install R packages in their home directory
23+
RUN chmod 555 /usr/local/lib/R /usr/local/lib/R/site-library/

Diff for: ‎docker-bits/6_remote-desktop.Dockerfile

+35-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
USER root
22

3+
ENV NB_UID=1000
4+
ENV NB_GID=100
5+
36
COPY clean-layer.sh /usr/bin/clean-layer.sh
47
RUN chmod +x /usr/bin/clean-layer.sh
58

@@ -275,14 +278,14 @@ RUN \
275278
#MISC Configuration Area
276279
#Copy over desktop files. First location is dropdown, then desktop, and make them executable
277280
COPY /desktop-files /usr/share/applications
278-
COPY /desktop-files /home/$NB_USER/Desktop
279-
RUN find /home/$NB_USER/Desktop -type f -iname "*.desktop" -exec chmod +x {} \;
281+
COPY /desktop-files $RESOURCES_PATH/desktop-files
280282

281283
#Copy over French Language files
282284
COPY French/mo-files/ /usr/share/locale/fr/LC_MESSAGES
283285

284286
#Configure the panel
285-
COPY ./desktop-files/.config/xfce4/xfce4-panel.xml /home/jovyan/.config/xfce4/xfconf/xfce-perchannel-xml/
287+
# Done at runtime
288+
# COPY ./desktop-files/.config/xfce4/xfce4-panel.xml /home/jovyan/.config/xfce4/xfconf/xfce-perchannel-xml/
286289

287290
#Removal area
288291
#Extra Icons
@@ -292,7 +295,7 @@ RUN apt-get remove -y -q light-locker
292295

293296

294297
# apt-get may result in root-owned directories/files under $HOME
295-
RUN usermod -l jovyan rstudio && \
298+
RUN usermod -l $NB_USER rstudio && \
296299
chown -R $NB_UID:$NB_GID $HOME
297300

298301
ENV NB_USER=$NB_USER
@@ -302,7 +305,8 @@ RUN apt-get update && apt-get install --yes websockify \
302305
&& cp /usr/lib/websockify/rebind.cpython-38-x86_64-linux-gnu.so /usr/lib/websockify/rebind.so \
303306
&& clean-layer.sh
304307

305-
ADD . /opt/install
308+
#ADD . /opt/install
309+
#RUN pwd && echo && ls /opt/install
306310

307311
#Install Miniconda
308312
#Has to be appended, else messes with qgis
@@ -322,8 +326,31 @@ RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-${CONDA_VERSION}
322326
echo "conda activate base" >> ~/.bashrc && \
323327
find /opt/conda/ -follow -type f -name '*.a' -delete && \
324328
find /opt/conda/ -follow -type f -name '*.js.map' -delete && \
325-
/opt/conda/bin/conda clean -afy
329+
/opt/conda/bin/conda clean -afy && \
330+
chown -R $NB_UID:$NB_GID /opt/conda
326331

327332
#Set Defaults
328-
ENV DEFAULT_JUPYTER_URL=desktop/?autoconnect=true
329-
ENV HOME=/home/jovyan
333+
ENV HOME=/home/$NB_USER
334+
335+
ARG NO_VNC_VERSION=1.2.0
336+
ARG NO_VNC_SHA=36c476b26df4684f1002e15c3d7e034c9e6ee4521e5fa8aac37309f954a07a01
337+
RUN pip3 install --force websockify==0.9.0 \
338+
&& wget https://github.com/novnc/noVNC/archive/refs/tags/v${NO_VNC_VERSION}.tar.gz -O /tmp/novnc.tar.gz \
339+
&& echo "${NO_VNC_SHA} /tmp/novnc.tar.gz" | sha256sum -c - \
340+
&& tar -xf /tmp/novnc.tar.gz -C /tmp/ \
341+
&& mv /tmp/noVNC-${NO_VNC_VERSION} /opt/novnc \
342+
&& rm /tmp/novnc.tar.gz \
343+
&& chown -R $NB_UID:$NB_GID /opt/novnc
344+
345+
COPY --chown=$NB_USER:100 canada.ico $RESOURCES_PATH/favicon.ico
346+
347+
USER root
348+
RUN apt-get update --yes \
349+
&& apt-get install --yes nginx \
350+
&& chown -R $NB_USER:100 /var/log/nginx \
351+
&& chown $NB_USER:100 /etc/nginx \
352+
&& chmod -R 755 /var/log/nginx \
353+
&& rm -rf /var/lib/apt/lists/*
354+
RUN chown -R $NB_USER /home/$NB_USER
355+
USER $NB_USER
356+
COPY --chown=$NB_USER:100 nginx.conf /etc/nginx/nginx.conf

Diff for: ‎docker-bits/7_remove_vulnerabilities.Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Remove libpdfbox-java due to CVE-2019-0228. See https://github.com/StatCan/kubeflow-containers/issues/249#issuecomment-834808115 for details.
22
# Issue opened https://github.com/jupyter/docker-stacks/issues/1299.
33
# This line of code should be removed once a solution or better alternative is found.
4+
USER root
45
RUN apt-get update --yes \
56
&& dpkg -r --force-depends libpdfbox-java \
67
&& rm -rf /var/lib/apt/lists/*
8+
USER $NB_USER

Diff for: ‎docker-bits/∞_CMD_remote-desktop.Dockerfile

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
# Configure container startup
22

3+
USER root
4+
35
WORKDIR /home/$NB_USER
46
EXPOSE 8888
57
COPY start-remote-desktop.sh /usr/local/bin/
6-
COPY mc-tenant-wrapper.sh /usr/local/bin/mc
8+
COPY mc-tenant-wrapper.sh /usr/local/bin/mc
9+
RUN chsh -s /bin/bash $NB_USER
10+
11+
# Add --user to all pip install calls
12+
COPY pip.conf /tmp/pip.conf
13+
RUN cat /tmp/pip.conf >> /etc/pip.conf && rm /tmp/pip.conf
14+
715
USER $NB_USER
816
ENTRYPOINT ["tini", "--"]
917
CMD ["start-remote-desktop.sh"]

Diff for: ‎output/jupyterlab-cpu/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,11 @@ ENV GIT_EXAMPLE_NOTEBOOKS=https://github.com/statcan/jupyter-notebooks
239239
# Remove libpdfbox-java due to CVE-2019-0228. See https://github.com/StatCan/kubeflow-containers/issues/249#issuecomment-834808115 for details.
240240
# Issue opened https://github.com/jupyter/docker-stacks/issues/1299.
241241
# This line of code should be removed once a solution or better alternative is found.
242+
USER root
242243
RUN apt-get update --yes \
243244
&& dpkg -r --force-depends libpdfbox-java \
244245
&& rm -rf /var/lib/apt/lists/*
246+
USER $NB_USER
245247

246248
###############################
247249
### docker-bits/∞_CMD.Dockerfile

Diff for: ‎output/jupyterlab-pytorch/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,11 @@ ENV GIT_EXAMPLE_NOTEBOOKS=https://github.com/statcan/jupyter-notebooks
336336
# Remove libpdfbox-java due to CVE-2019-0228. See https://github.com/StatCan/kubeflow-containers/issues/249#issuecomment-834808115 for details.
337337
# Issue opened https://github.com/jupyter/docker-stacks/issues/1299.
338338
# This line of code should be removed once a solution or better alternative is found.
339+
USER root
339340
RUN apt-get update --yes \
340341
&& dpkg -r --force-depends libpdfbox-java \
341342
&& rm -rf /var/lib/apt/lists/*
343+
USER $NB_USER
342344

343345
###############################
344346
### docker-bits/∞_CMD.Dockerfile

Diff for: ‎output/jupyterlab-tensorflow/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,11 @@ ENV GIT_EXAMPLE_NOTEBOOKS=https://github.com/statcan/jupyter-notebooks
331331
# Remove libpdfbox-java due to CVE-2019-0228. See https://github.com/StatCan/kubeflow-containers/issues/249#issuecomment-834808115 for details.
332332
# Issue opened https://github.com/jupyter/docker-stacks/issues/1299.
333333
# This line of code should be removed once a solution or better alternative is found.
334+
USER root
334335
RUN apt-get update --yes \
335336
&& dpkg -r --force-depends libpdfbox-java \
336337
&& rm -rf /var/lib/apt/lists/*
338+
USER $NB_USER
337339

338340
###############################
339341
### docker-bits/∞_CMD.Dockerfile

Diff for: ‎output/remote-desktop/Dockerfile

+52-12
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
### docker-bits/0_Rocker.Dockerfile
44
###############################
55

6-
# Rocker/geospatial is tagged by R version number. They are not clear on whether they'll change those tagged
6+
# Rocker/geospatial is tagged by R version number. They are not clear on whether they'll change those tagged
77
# images for hotfixes, so always pin tag and digest to prevent unexpected upstream changes
88
FROM rocker/geospatial:4.0.3@sha256:9e00ab4fec7b38a0edbadb07e7554bf3b7fa34d15c6fe42522a09ae88d336219
99

1010
# For compatibility with docker stacks
1111
ARG NB_USER="jovyan"
1212
ARG HOME=/home/$NB_USER
13-
ARG NB_UID="1000"
14-
ARG NB_GID="100"
13+
ENV NB_UID="1000"
14+
ENV NB_GID="100"
1515

1616
USER root
1717
ENV PATH="/home/jovyan/.local/bin/:${PATH}"
@@ -24,6 +24,9 @@ RUN /rocker_scripts/install_shiny_server.sh \
2424
&& pip3 install jupyter \
2525
&& rm -rf /var/lib/apt/lists/*
2626

27+
# Users should install R packages in their home directory
28+
RUN chmod 555 /usr/local/lib/R /usr/local/lib/R/site-library/
29+
2730
###############################
2831
### docker-bits/3_Kubeflow.Dockerfile
2932
###############################
@@ -113,6 +116,9 @@ RUN curl -LO "${KUBECTL_URL}" \
113116

114117
USER root
115118

119+
ENV NB_UID=1000
120+
ENV NB_GID=100
121+
116122
COPY clean-layer.sh /usr/bin/clean-layer.sh
117123
RUN chmod +x /usr/bin/clean-layer.sh
118124

@@ -388,14 +394,14 @@ RUN \
388394
#MISC Configuration Area
389395
#Copy over desktop files. First location is dropdown, then desktop, and make them executable
390396
COPY /desktop-files /usr/share/applications
391-
COPY /desktop-files /home/$NB_USER/Desktop
392-
RUN find /home/$NB_USER/Desktop -type f -iname "*.desktop" -exec chmod +x {} \;
397+
COPY /desktop-files $RESOURCES_PATH/desktop-files
393398

394399
#Copy over French Language files
395400
COPY French/mo-files/ /usr/share/locale/fr/LC_MESSAGES
396401

397402
#Configure the panel
398-
COPY ./desktop-files/.config/xfce4/xfce4-panel.xml /home/jovyan/.config/xfce4/xfconf/xfce-perchannel-xml/
403+
# Done at runtime
404+
# COPY ./desktop-files/.config/xfce4/xfce4-panel.xml /home/jovyan/.config/xfce4/xfconf/xfce-perchannel-xml/
399405

400406
#Removal area
401407
#Extra Icons
@@ -405,7 +411,7 @@ RUN apt-get remove -y -q light-locker
405411

406412

407413
# apt-get may result in root-owned directories/files under $HOME
408-
RUN usermod -l jovyan rstudio && \
414+
RUN usermod -l $NB_USER rstudio && \
409415
chown -R $NB_UID:$NB_GID $HOME
410416

411417
ENV NB_USER=$NB_USER
@@ -415,7 +421,8 @@ RUN apt-get update && apt-get install --yes websockify \
415421
&& cp /usr/lib/websockify/rebind.cpython-38-x86_64-linux-gnu.so /usr/lib/websockify/rebind.so \
416422
&& clean-layer.sh
417423

418-
ADD . /opt/install
424+
#ADD . /opt/install
425+
#RUN pwd && echo && ls /opt/install
419426

420427
#Install Miniconda
421428
#Has to be appended, else messes with qgis
@@ -435,11 +442,34 @@ RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-${CONDA_VERSION}
435442
echo "conda activate base" >> ~/.bashrc && \
436443
find /opt/conda/ -follow -type f -name '*.a' -delete && \
437444
find /opt/conda/ -follow -type f -name '*.js.map' -delete && \
438-
/opt/conda/bin/conda clean -afy
445+
/opt/conda/bin/conda clean -afy && \
446+
chown -R $NB_UID:$NB_GID /opt/conda
439447

440448
#Set Defaults
441-
ENV DEFAULT_JUPYTER_URL=desktop/?autoconnect=true
442-
ENV HOME=/home/jovyan
449+
ENV HOME=/home/$NB_USER
450+
451+
ARG NO_VNC_VERSION=1.2.0
452+
ARG NO_VNC_SHA=36c476b26df4684f1002e15c3d7e034c9e6ee4521e5fa8aac37309f954a07a01
453+
RUN pip3 install --force websockify==0.9.0 \
454+
&& wget https://github.com/novnc/noVNC/archive/refs/tags/v${NO_VNC_VERSION}.tar.gz -O /tmp/novnc.tar.gz \
455+
&& echo "${NO_VNC_SHA} /tmp/novnc.tar.gz" | sha256sum -c - \
456+
&& tar -xf /tmp/novnc.tar.gz -C /tmp/ \
457+
&& mv /tmp/noVNC-${NO_VNC_VERSION} /opt/novnc \
458+
&& rm /tmp/novnc.tar.gz \
459+
&& chown -R $NB_UID:$NB_GID /opt/novnc
460+
461+
COPY --chown=$NB_USER:100 canada.ico $RESOURCES_PATH/favicon.ico
462+
463+
USER root
464+
RUN apt-get update --yes \
465+
&& apt-get install --yes nginx \
466+
&& chown -R $NB_USER:100 /var/log/nginx \
467+
&& chown $NB_USER:100 /etc/nginx \
468+
&& chmod -R 755 /var/log/nginx \
469+
&& rm -rf /var/lib/apt/lists/*
470+
RUN chown -R $NB_USER /home/$NB_USER
471+
USER $NB_USER
472+
COPY --chown=$NB_USER:100 nginx.conf /etc/nginx/nginx.conf
443473

444474
###############################
445475
### docker-bits/7_remove_vulnerabilities.Dockerfile
@@ -448,20 +478,30 @@ ENV HOME=/home/jovyan
448478
# Remove libpdfbox-java due to CVE-2019-0228. See https://github.com/StatCan/kubeflow-containers/issues/249#issuecomment-834808115 for details.
449479
# Issue opened https://github.com/jupyter/docker-stacks/issues/1299.
450480
# This line of code should be removed once a solution or better alternative is found.
481+
USER root
451482
RUN apt-get update --yes \
452483
&& dpkg -r --force-depends libpdfbox-java \
453484
&& rm -rf /var/lib/apt/lists/*
485+
USER $NB_USER
454486

455487
###############################
456488
### docker-bits/∞_CMD_remote-desktop.Dockerfile
457489
###############################
458490

459491
# Configure container startup
460492

493+
USER root
494+
461495
WORKDIR /home/$NB_USER
462496
EXPOSE 8888
463497
COPY start-remote-desktop.sh /usr/local/bin/
464-
COPY mc-tenant-wrapper.sh /usr/local/bin/mc
498+
COPY mc-tenant-wrapper.sh /usr/local/bin/mc
499+
RUN chsh -s /bin/bash $NB_USER
500+
501+
# Add --user to all pip install calls
502+
COPY pip.conf /tmp/pip.conf
503+
RUN cat /tmp/pip.conf >> /etc/pip.conf && rm /tmp/pip.conf
504+
465505
USER $NB_USER
466506
ENTRYPOINT ["tini", "--"]
467507
CMD ["start-remote-desktop.sh"]

Diff for: ‎output/remote-desktop/canada.ico

168 KB
Binary file not shown.

Diff for: ‎output/remote-desktop/nginx.conf

+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
pid /tmp/nginx.pid;
2+
3+
events {
4+
# No special events for this simple setup
5+
#worker_connections 100;
6+
}
7+
8+
http {
9+
10+
include mime.types;
11+
#map $http_upgrade $connection_upgrade {
12+
# default upgrade;
13+
# '' close;
14+
#}
15+
16+
# map $upstream_http_location $new_location {
17+
# default .$upstream_http_location;
18+
#}
19+
20+
21+
client_max_body_size 10G;
22+
client_body_timeout 300s;
23+
client_header_timeout 120s;
24+
25+
proxy_connect_timeout 600;
26+
proxy_send_timeout 600;
27+
proxy_read_timeout 600;
28+
send_timeout 600;
29+
30+
31+
upstream vnc_proxy {
32+
server 0.0.0.0:5678;
33+
}
34+
35+
server {
36+
37+
absolute_redirect off;
38+
# Set a number of log, temp and cache file options that will otherwise
39+
# default to restricted locations accessible only to root.
40+
access_log /tmp/nginx_host.access.log;
41+
error_log /tmp/nginx_error.log;
42+
client_body_temp_path /tmp/client_body;
43+
fastcgi_temp_path /tmp/fastcgi_temp;
44+
proxy_temp_path /tmp/proxy_temp;
45+
scgi_temp_path /tmp/scgi_temp;
46+
uwsgi_temp_path /tmp/uwsgi_temp;
47+
48+
# Port forwarding stuff
49+
listen 8888 default_server;
50+
listen [::]:8888 default_server;
51+
52+
# root /var/www/html;
53+
root /tmp/novnc;
54+
55+
# Add index.php to the list if you are using PHP
56+
index vnc.html;
57+
58+
server_name _;
59+
60+
location = "/favicon.ico" {
61+
# use favicon in resources folder
62+
auth_basic off;
63+
alias /tmp/favicon.ico;
64+
}
65+
66+
#location /app/ {
67+
# autoindex on;
68+
# root /tmp/novnc/app;
69+
#}
70+
71+
#location ~ \.css {
72+
# add_header Content-Type text/css;
73+
#}
74+
#location ~ \.js {
75+
# add_header Content-Type application/x-javascript;
76+
#}
77+
78+
# 301 try_file for trailing slash
79+
location ~ ^([^.\?]*[^/])$ {
80+
try_files $uri @addslash;
81+
}
82+
83+
# 301 redirect for trailing slash
84+
location @addslash {
85+
return 301 $uri/$is_args$args;
86+
}
87+
88+
89+
location ${NB_PREFIX} {
90+
rewrite ${NB_PREFIX}(.*) $1 break;
91+
proxy_pass http://0.0.0.0:8888;
92+
proxy_redirect off;
93+
proxy_set_header Host $host;
94+
95+
gzip on;
96+
gzip_proxied any;
97+
gzip_types *;
98+
99+
}
100+
101+
location = ${NB_PREFIX}/websockify {
102+
rewrite ${NB_PREFIX}/(.*) /$1 break;
103+
104+
set $delimeter "";
105+
106+
if ($is_args) {
107+
set $delimeter "&";
108+
}
109+
110+
set $args "$args${delimeter}resize=true";
111+
proxy_http_version 1.1;
112+
proxy_pass http://vnc_proxy/;
113+
proxy_set_header Upgrade $http_upgrade;
114+
proxy_set_header Connection "upgrade";
115+
116+
# VNC connection timeout
117+
proxy_read_timeout 61s;
118+
119+
# Disable cache
120+
proxy_buffering off;
121+
122+
gzip on;
123+
gzip_proxied any;
124+
gzip_types *;
125+
126+
}
127+
128+
location /websockify {
129+
#rewrite ${NB_PREFIX}/(.*) /$1 break;
130+
proxy_http_version 1.1;
131+
proxy_pass http://vnc_proxy/;
132+
proxy_set_header Upgrade $http_upgrade;
133+
proxy_set_header Connection "upgrade";
134+
135+
# VNC connection timeout
136+
proxy_read_timeout 61s;
137+
138+
# Disable cache
139+
proxy_buffering off;
140+
141+
gzip on;
142+
gzip_proxied any;
143+
gzip_types *;
144+
145+
}
146+
147+
148+
location ${NB_PREFIX}/websockify {
149+
#rewrite ${NB_PREFIX}/(.*) /$1 break;
150+
proxy_http_version 1.1;
151+
proxy_pass http://vnc_proxy/;
152+
proxy_set_header Upgrade $http_upgrade;
153+
proxy_set_header Connection "upgrade";
154+
155+
# VNC connection timeout
156+
proxy_read_timeout 61s;
157+
158+
# Disable cache
159+
proxy_buffering off;
160+
161+
gzip on;
162+
gzip_proxied any;
163+
gzip_types *;
164+
165+
}
166+
167+
location / {
168+
index vnc.html;
169+
root /usr/local/lib/python3.8/dist-packages/jupyter_desktop/share/web/noVNC-1.1.0/;
170+
try_files $uri $uri/ /vnc.html?resize=true;
171+
}
172+
173+
location = /healthy {
174+
auth_basic off;
175+
return 200;
176+
}
177+
178+
location = /ping {
179+
auth_basic off;
180+
return 200;
181+
}
182+
183+
error_page 404 ${NB_PREFIX}/;
184+
# location @error_page {
185+
# root /var/www/html/;
186+
# rewrite ^ https://domain.com/error/index.html;
187+
# break;
188+
# }
189+
190+
}
191+
}

Diff for: ‎output/remote-desktop/start-remote-desktop.sh

+80-11
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,47 @@ if [ -d /var/run/secrets/kubernetes.io/serviceaccount ]; then
44
while ! curl -s -f http://127.0.0.1:15020/healthz/ready; do sleep 1; done
55
fi
66

7+
test -z "$GIT_EXAMPLE_NOTEBOOKS" || git clone "$GIT_EXAMPLE_NOTEBOOKS"
8+
9+
10+
if conda --help > /dev/null 2>&1; then
11+
conda init bash
12+
conda init zsh
13+
fi
14+
715
# Configure the language
8-
# Note that our inherited image already has settings for en_US
916
if [ -n "${KF_LANG}" ]; then
17+
if [ "${KF_LANG}" = "en" ]; then
18+
export LANG="en_US.utf8"
19+
else
20+
export LANG="fr_CA.utf8"
21+
# User's browser lang is set to french, open jupyterlab in french (fr_FR)
22+
if [ "${DEFAULT_JUPYTER_URL}" != "/rstudio" ]; then
23+
export LANG="fr_FR"
24+
lang_file="$HOME/.jupyter/lab/user-settings/@jupyterlab/translation-extension/plugin.jupyterlab-settings"
25+
mkdir -p "$(dirname "${lang_file}")" && touch $lang_file
26+
( echo '{'
27+
echo ' // Langue'
28+
echo ' // @jupyterlab/translation-extension:plugin'
29+
echo ' // Paramètres de langue.'
30+
echo -e ' // ****************************************\n'
31+
echo ' // Langue locale'
32+
echo ' // Définit la langue d'\''affichage de l'\''interface. Exemples: '\''es_CO'\'', '\''fr'\''.'
33+
echo ' "locale": "'${LANG}'"'
34+
echo '}'
35+
) >> $lang_file
36+
fi
37+
fi
38+
39+
# VS-Code i18n stuff
1040
if [ "${KF_LANG}" = "fr" ]; then
1141
export LANG="fr_FR.UTF-8"
1242
export LANGUAGE="fr_FR.UTF-8"
1343
export LC_ALL="fr_FR.UTF-8"
1444
#Set the locale for vscode
15-
jq -e '.locale="fr"' /home/$NB_USER/.vscode/argv.json > file.json.tmp && cp file.json.tmp /home/$NB_USER/.vscode/argv.json
45+
mkdir -p $HOME/.vscode
46+
jq -e '.locale="fr"' $HOME/.vscode/argv.json > /tmp/file.json.tmp
47+
mv /tmp/file.json.tmp $HOME/.vscode/argv.json
1648
fi
1749
fi
1850
# Configure KFP multi-user
@@ -23,12 +55,49 @@ cat <<EOF > $HOME/.config/kfp/context.json
2355
EOF
2456
fi
2557

26-
jupyter notebook --notebook-dir=/home/${NB_USER} \
27-
--ip=0.0.0.0 \
28-
--no-browser \
29-
--port=8888 \
30-
--NotebookApp.token='' \
31-
--NotebookApp.password='' \
32-
--NotebookApp.allow_origin='*' \
33-
--NotebookApp.base_url=${NB_PREFIX} \
34-
--NotebookApp.default_url=${DEFAULT_JUPYTER_URL:-/tree}
58+
59+
# Create desktop shortcuts
60+
if [ -d $RESOURCES_PATH/desktop-files ]; then
61+
mkdir -p ~/.local/share/applications/ $HOME/Desktop
62+
echo find $RESOURCES_PATH/desktop-files/ $HOME/Desktop/
63+
find $RESOURCES_PATH/desktop-files/ -type f -iname "*.desktop" -exec cp {} $HOME/Desktop/ \;
64+
rsync $RESOURCES_PATH/desktop-files/.config/ $HOME/.config/
65+
find $HOME/Desktop -type f -iname "*.desktop" -exec chmod +x {} \;
66+
mkdir -p $HOME/.config/xfce4/xfconf/xfce-perchannel-xml/
67+
cp /opt/install/desktop-files/.config/xfce4/xfce4-panel.xml $HOME/.config/xfce4/xfconf/xfce-perchannel-xml/
68+
fi
69+
70+
mkdir -p $HOME/.vnc
71+
[ -f $HOME/.vnc/xstartup ] || {
72+
cat <<EOF > $HOME/.vnc/xstartup
73+
#!/bin/sh
74+
75+
unset SESSION_MANAGER
76+
unset DBUS_SESSION_BUS_ADDRESS
77+
startxfce4 &
78+
79+
# Makes an unbelievable difference in speed
80+
(sleep 10 && xfconf-query -c xfwm4 -p /general/use_compositing -s false && dconf write /org/gnome/terminal/legacy/profiles/custom-command "'/bin/bash'") &
81+
EOF
82+
chmod +x $HOME/.vnc/xstartup
83+
}
84+
85+
mkdir -p /tmp/vnc-socket/
86+
VNC_SOCKET=$(mktemp /tmp/vnc-socket/vnc-XXXXXX.sock)
87+
trap "rm -f $VNC_SOCKET" EXIT
88+
89+
vncserver -SecurityTypes None -rfbunixpath $VNC_SOCKET -geometry 1680x1050 :1
90+
cat $HOME/.vnc/*.log
91+
92+
# Launch noVNC
93+
(
94+
# cd /tmp/novnc/
95+
cd /usr/local/lib/python3.8/dist-packages/jupyter_desktop/share/web/noVNC-1.1.0/
96+
./utils/launch.sh --web $(pwd) --vnc --unix-target=$VNC_SOCKET --listen 5678
97+
) &
98+
99+
NB_PREFIX=${NB_PREFIX:-/vnc}
100+
sed -i "s~\${NB_PREFIX}~$NB_PREFIX~g" /etc/nginx/nginx.conf
101+
102+
nginx
103+
wait

Diff for: ‎output/rstudio/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,11 @@ ENV GIT_EXAMPLE_NOTEBOOKS=https://github.com/statcan/R-notebooks.git
169169
# Remove libpdfbox-java due to CVE-2019-0228. See https://github.com/StatCan/kubeflow-containers/issues/249#issuecomment-834808115 for details.
170170
# Issue opened https://github.com/jupyter/docker-stacks/issues/1299.
171171
# This line of code should be removed once a solution or better alternative is found.
172+
USER root
172173
RUN apt-get update --yes \
173174
&& dpkg -r --force-depends libpdfbox-java \
174175
&& rm -rf /var/lib/apt/lists/*
176+
USER $NB_USER
175177

176178
###############################
177179
### docker-bits/∞_CMD.Dockerfile

Diff for: ‎requirements-dev.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ requests
77
# sphinx-intl
88
tabulate
99
# transifex-client
10+
six

Diff for: ‎resources/remote-desktop/canada.ico

168 KB
Binary file not shown.

Diff for: ‎resources/remote-desktop/nginx.conf

+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
pid /tmp/nginx.pid;
2+
3+
events {
4+
# No special events for this simple setup
5+
#worker_connections 100;
6+
}
7+
8+
http {
9+
10+
include mime.types;
11+
#map $http_upgrade $connection_upgrade {
12+
# default upgrade;
13+
# '' close;
14+
#}
15+
16+
# map $upstream_http_location $new_location {
17+
# default .$upstream_http_location;
18+
#}
19+
20+
21+
client_max_body_size 10G;
22+
client_body_timeout 300s;
23+
client_header_timeout 120s;
24+
25+
proxy_connect_timeout 600;
26+
proxy_send_timeout 600;
27+
proxy_read_timeout 600;
28+
send_timeout 600;
29+
30+
31+
upstream vnc_proxy {
32+
server 0.0.0.0:5678;
33+
}
34+
35+
server {
36+
37+
absolute_redirect off;
38+
# Set a number of log, temp and cache file options that will otherwise
39+
# default to restricted locations accessible only to root.
40+
access_log /tmp/nginx_host.access.log;
41+
error_log /tmp/nginx_error.log;
42+
client_body_temp_path /tmp/client_body;
43+
fastcgi_temp_path /tmp/fastcgi_temp;
44+
proxy_temp_path /tmp/proxy_temp;
45+
scgi_temp_path /tmp/scgi_temp;
46+
uwsgi_temp_path /tmp/uwsgi_temp;
47+
48+
# Port forwarding stuff
49+
listen 8888 default_server;
50+
listen [::]:8888 default_server;
51+
52+
# root /var/www/html;
53+
root /tmp/novnc;
54+
55+
# Add index.php to the list if you are using PHP
56+
index vnc.html;
57+
58+
server_name _;
59+
60+
location = "/favicon.ico" {
61+
# use favicon in resources folder
62+
auth_basic off;
63+
alias /tmp/favicon.ico;
64+
}
65+
66+
#location /app/ {
67+
# autoindex on;
68+
# root /tmp/novnc/app;
69+
#}
70+
71+
#location ~ \.css {
72+
# add_header Content-Type text/css;
73+
#}
74+
#location ~ \.js {
75+
# add_header Content-Type application/x-javascript;
76+
#}
77+
78+
# 301 try_file for trailing slash
79+
location ~ ^([^.\?]*[^/])$ {
80+
try_files $uri @addslash;
81+
}
82+
83+
# 301 redirect for trailing slash
84+
location @addslash {
85+
return 301 $uri/$is_args$args;
86+
}
87+
88+
89+
location ${NB_PREFIX} {
90+
rewrite ${NB_PREFIX}(.*) $1 break;
91+
proxy_pass http://0.0.0.0:8888;
92+
proxy_redirect off;
93+
proxy_set_header Host $host;
94+
95+
gzip on;
96+
gzip_proxied any;
97+
gzip_types *;
98+
99+
}
100+
101+
location = ${NB_PREFIX}/websockify {
102+
rewrite ${NB_PREFIX}/(.*) /$1 break;
103+
104+
set $delimeter "";
105+
106+
if ($is_args) {
107+
set $delimeter "&";
108+
}
109+
110+
set $args "$args${delimeter}resize=true";
111+
proxy_http_version 1.1;
112+
proxy_pass http://vnc_proxy/;
113+
proxy_set_header Upgrade $http_upgrade;
114+
proxy_set_header Connection "upgrade";
115+
116+
# VNC connection timeout
117+
proxy_read_timeout 61s;
118+
119+
# Disable cache
120+
proxy_buffering off;
121+
122+
gzip on;
123+
gzip_proxied any;
124+
gzip_types *;
125+
126+
}
127+
128+
location /websockify {
129+
#rewrite ${NB_PREFIX}/(.*) /$1 break;
130+
proxy_http_version 1.1;
131+
proxy_pass http://vnc_proxy/;
132+
proxy_set_header Upgrade $http_upgrade;
133+
proxy_set_header Connection "upgrade";
134+
135+
# VNC connection timeout
136+
proxy_read_timeout 61s;
137+
138+
# Disable cache
139+
proxy_buffering off;
140+
141+
gzip on;
142+
gzip_proxied any;
143+
gzip_types *;
144+
145+
}
146+
147+
148+
location ${NB_PREFIX}/websockify {
149+
#rewrite ${NB_PREFIX}/(.*) /$1 break;
150+
proxy_http_version 1.1;
151+
proxy_pass http://vnc_proxy/;
152+
proxy_set_header Upgrade $http_upgrade;
153+
proxy_set_header Connection "upgrade";
154+
155+
# VNC connection timeout
156+
proxy_read_timeout 61s;
157+
158+
# Disable cache
159+
proxy_buffering off;
160+
161+
gzip on;
162+
gzip_proxied any;
163+
gzip_types *;
164+
165+
}
166+
167+
location / {
168+
index vnc.html;
169+
root /usr/local/lib/python3.8/dist-packages/jupyter_desktop/share/web/noVNC-1.1.0/;
170+
try_files $uri $uri/ /vnc.html?resize=true;
171+
}
172+
173+
location = /healthy {
174+
auth_basic off;
175+
return 200;
176+
}
177+
178+
location = /ping {
179+
auth_basic off;
180+
return 200;
181+
}
182+
183+
error_page 404 ${NB_PREFIX}/;
184+
# location @error_page {
185+
# root /var/www/html/;
186+
# rewrite ^ https://domain.com/error/index.html;
187+
# break;
188+
# }
189+
190+
}
191+
}

Diff for: ‎resources/remote-desktop/start-remote-desktop.sh

+80-11
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,47 @@ if [ -d /var/run/secrets/kubernetes.io/serviceaccount ]; then
44
while ! curl -s -f http://127.0.0.1:15020/healthz/ready; do sleep 1; done
55
fi
66

7+
test -z "$GIT_EXAMPLE_NOTEBOOKS" || git clone "$GIT_EXAMPLE_NOTEBOOKS"
8+
9+
10+
if conda --help > /dev/null 2>&1; then
11+
conda init bash
12+
conda init zsh
13+
fi
14+
715
# Configure the language
8-
# Note that our inherited image already has settings for en_US
916
if [ -n "${KF_LANG}" ]; then
17+
if [ "${KF_LANG}" = "en" ]; then
18+
export LANG="en_US.utf8"
19+
else
20+
export LANG="fr_CA.utf8"
21+
# User's browser lang is set to french, open jupyterlab in french (fr_FR)
22+
if [ "${DEFAULT_JUPYTER_URL}" != "/rstudio" ]; then
23+
export LANG="fr_FR"
24+
lang_file="$HOME/.jupyter/lab/user-settings/@jupyterlab/translation-extension/plugin.jupyterlab-settings"
25+
mkdir -p "$(dirname "${lang_file}")" && touch $lang_file
26+
( echo '{'
27+
echo ' // Langue'
28+
echo ' // @jupyterlab/translation-extension:plugin'
29+
echo ' // Paramètres de langue.'
30+
echo -e ' // ****************************************\n'
31+
echo ' // Langue locale'
32+
echo ' // Définit la langue d'\''affichage de l'\''interface. Exemples: '\''es_CO'\'', '\''fr'\''.'
33+
echo ' "locale": "'${LANG}'"'
34+
echo '}'
35+
) >> $lang_file
36+
fi
37+
fi
38+
39+
# VS-Code i18n stuff
1040
if [ "${KF_LANG}" = "fr" ]; then
1141
export LANG="fr_FR.UTF-8"
1242
export LANGUAGE="fr_FR.UTF-8"
1343
export LC_ALL="fr_FR.UTF-8"
1444
#Set the locale for vscode
15-
jq -e '.locale="fr"' /home/$NB_USER/.vscode/argv.json > file.json.tmp && cp file.json.tmp /home/$NB_USER/.vscode/argv.json
45+
mkdir -p $HOME/.vscode
46+
jq -e '.locale="fr"' $HOME/.vscode/argv.json > /tmp/file.json.tmp
47+
mv /tmp/file.json.tmp $HOME/.vscode/argv.json
1648
fi
1749
fi
1850
# Configure KFP multi-user
@@ -23,12 +55,49 @@ cat <<EOF > $HOME/.config/kfp/context.json
2355
EOF
2456
fi
2557

26-
jupyter notebook --notebook-dir=/home/${NB_USER} \
27-
--ip=0.0.0.0 \
28-
--no-browser \
29-
--port=8888 \
30-
--NotebookApp.token='' \
31-
--NotebookApp.password='' \
32-
--NotebookApp.allow_origin='*' \
33-
--NotebookApp.base_url=${NB_PREFIX} \
34-
--NotebookApp.default_url=${DEFAULT_JUPYTER_URL:-/tree}
58+
59+
# Create desktop shortcuts
60+
if [ -d $RESOURCES_PATH/desktop-files ]; then
61+
mkdir -p ~/.local/share/applications/ $HOME/Desktop
62+
echo find $RESOURCES_PATH/desktop-files/ $HOME/Desktop/
63+
find $RESOURCES_PATH/desktop-files/ -type f -iname "*.desktop" -exec cp {} $HOME/Desktop/ \;
64+
rsync $RESOURCES_PATH/desktop-files/.config/ $HOME/.config/
65+
find $HOME/Desktop -type f -iname "*.desktop" -exec chmod +x {} \;
66+
mkdir -p $HOME/.config/xfce4/xfconf/xfce-perchannel-xml/
67+
cp /opt/install/desktop-files/.config/xfce4/xfce4-panel.xml $HOME/.config/xfce4/xfconf/xfce-perchannel-xml/
68+
fi
69+
70+
mkdir -p $HOME/.vnc
71+
[ -f $HOME/.vnc/xstartup ] || {
72+
cat <<EOF > $HOME/.vnc/xstartup
73+
#!/bin/sh
74+
75+
unset SESSION_MANAGER
76+
unset DBUS_SESSION_BUS_ADDRESS
77+
startxfce4 &
78+
79+
# Makes an unbelievable difference in speed
80+
(sleep 10 && xfconf-query -c xfwm4 -p /general/use_compositing -s false && dconf write /org/gnome/terminal/legacy/profiles/custom-command "'/bin/bash'") &
81+
EOF
82+
chmod +x $HOME/.vnc/xstartup
83+
}
84+
85+
mkdir -p /tmp/vnc-socket/
86+
VNC_SOCKET=$(mktemp /tmp/vnc-socket/vnc-XXXXXX.sock)
87+
trap "rm -f $VNC_SOCKET" EXIT
88+
89+
vncserver -SecurityTypes None -rfbunixpath $VNC_SOCKET -geometry 1680x1050 :1
90+
cat $HOME/.vnc/*.log
91+
92+
# Launch noVNC
93+
(
94+
# cd /tmp/novnc/
95+
cd /usr/local/lib/python3.8/dist-packages/jupyter_desktop/share/web/noVNC-1.1.0/
96+
./utils/launch.sh --web $(pwd) --vnc --unix-target=$VNC_SOCKET --listen 5678
97+
) &
98+
99+
NB_PREFIX=${NB_PREFIX:-/vnc}
100+
sed -i "s~\${NB_PREFIX}~$NB_PREFIX~g" /etc/nginx/nginx.conf
101+
102+
nginx
103+
wait

Diff for: ‎tests/general/test_notebook.py

+27-9
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
LOGGER = logging.getLogger(__name__)
66

7+
78
def test_server_alive(container, http_client, url="http://localhost:8888"):
89
"""Notebook server should eventually appear with a recognizable page."""
10+
11+
# Redirect url to NB_PREFIX if it is set in the container environment
12+
url = "{}{}/".format(url, container.kwargs['environment']['NB_PREFIX'])
13+
914
LOGGER.info("Running test_server_alive")
1015
LOGGER.info("launching the container")
1116
container.run()
@@ -14,15 +19,28 @@ def test_server_alive(container, http_client, url="http://localhost:8888"):
1419
resp.raise_for_status()
1520
LOGGER.debug(f"got text from url: {resp.text}")
1621

17-
# Not sure why but some flavors of JupyterLab images don't hit all of these.
22+
# Not sure why but some flavors of JupyterLab images don't hit all of these.
1823
# Trying to catch several different acceptable looks.
1924
# Also accepting RStudio
20-
# TODO: This general test accepts many different images.
25+
# TODO: This general test accepts many different images.
2126
# Could refactor to have specific tests that are more pointed
22-
assert any((
23-
"<title>JupyterLab" in resp.text,
24-
"<title>Jupyter Notebook</title>" in resp.text,
25-
"<title>RStudio:" in resp.text, # RStudio
26-
'<html lang="en" class="noVNC_loading">' in resp.text, # remote-desktop using noVNC
27-
'<span id="running_list_info">Currently running Jupyter processes</span>' in resp.text,
28-
)), "Image does not appear to start to JupyterLab page. Try starting yourself and browsing to it to see what is happening"
27+
28+
# Define various possible expected texts (this catches different expected outcomes like a JupyterLab interface,
29+
# RStudio, etc.). If any of these pass, the test passes
30+
assertion_expected_texts = [
31+
"<title>JupyterLab",
32+
"<title>Jupyter Notebook</title>",
33+
"<title>RStudio:",
34+
'<html lang="en" class="noVNC_loading">', # Remote desktop
35+
'<html lang="fr" class="noVNC_loading">', # Remote desktop
36+
'<span id="running_list_info">Currently running Jupyter processes</span>',
37+
]
38+
assertions = [s in resp.text for s in assertion_expected_texts]
39+
40+
# Log assertions to screen for easier debugging
41+
LOGGER.debug("Status of tests look for that indicate notebook is up:")
42+
for i, (text, assertion) in enumerate(zip(assertion_expected_texts, assertions)):
43+
LOGGER.debug(f"{i}: '{text}' in resp.text = {assertion}")
44+
45+
assert any(assertions), "Image does not appear to start to JupyterLab page. " \
46+
"Try starting yourself and browsing to it to see what is happening"

0 commit comments

Comments
 (0)
Please sign in to comment.