Skip to content

Commit 858b1b8

Browse files
jesuinojiridanek
andauthored
RHOAIENG-16568: [Bug] Unable to download notebook as a PDF from JupyterLab Workbenches (#1030)
* RHOAIENG-16568: [Bug] Unable to download notebook as a PDF from JupyterLab Workbenches * Running installation from a script * Adding test and fixing path * Fixing Script file name * Using minimal tmp file instead a fixed file * Removing and ignoring logs * Adding tex live to missing Dockerfiles * Formatting * Review changes * Removing unwanted line * Fixing type * Copying configuration in all images * Removing year from the TeXLive installation * Adding pandoc for a complete PDF export support * Updating comment about TeX live installation * Improving PDF export test * pandoc latest version and ignoring message * formatting fix * add "/usr/local/pandoc/bin/pandoc" to config.toml --------- Co-authored-by: Jiri Daněk <[email protected]>
1 parent 357ab0a commit 858b1b8

File tree

14 files changed

+168
-2
lines changed

14 files changed

+168
-2
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ MANIFEST
3737
pip-log.txt
3838
pip-delete-this-directory.txt
3939

40+
# Test logs
41+
logs/pytest-logs.txt
42+
4043
# Unit test / coverage reports
4144
htmlcov/
4245
.tox/

jupyter/datascience/ubi9-python-3.11/Dockerfile.cpu

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ WORKDIR /opt/app-root/bin
4949
COPY ${JUPYTER_REUSABLE_UTILS} utils/
5050
COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
5151

52+
USER 0
53+
54+
# Dependencies for PDF export
55+
RUN ./utils/install_pdf_deps.sh
56+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
57+
58+
USER 1001
59+
5260
WORKDIR /opt/app-root/src
5361

5462
ENTRYPOINT ["start-notebook.sh"]
@@ -107,6 +115,8 @@ RUN echo "Installing softwares and packages" && \
107115
rm /opt/app-root/share/jupyter/metadata/runtime-images/*.json && \
108116
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
109117
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
118+
# copy jupyter configuration
119+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
110120
# Disable announcement plugin of jupyterlab \
111121
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
112122
# Apply JupyterLab addons \

jupyter/minimal/ubi9-python-3.11/Dockerfile.cpu

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ RUN pip install --no-cache-dir -U "micropipenv[toml]"
1919

2020
# Install the oc client
2121
RUN curl -L https://mirror.openshift.com/pub/openshift-v4/$(uname -m)/clients/ocp/stable/openshift-client-linux.tar.gz \
22-
-o /tmp/openshift-client-linux.tar.gz && \
22+
-o /tmp/openshift-client-linux.tar.gz && \
2323
tar -xzvf /tmp/openshift-client-linux.tar.gz oc && \
2424
rm -f /tmp/openshift-client-linux.tar.gz
2525

@@ -45,6 +45,14 @@ WORKDIR /opt/app-root/bin
4545

4646
COPY ${JUPYTER_REUSABLE_UTILS} utils/
4747

48+
USER 0
49+
50+
# Dependencies for PDF export
51+
RUN ./utils/install_pdf_deps.sh
52+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
53+
54+
USER 1001
55+
4856
COPY ${MINIMAL_SOURCE_CODE}/Pipfile.lock ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
4957

5058
# Install Python dependencies from Pipfile.lock file
@@ -55,12 +63,14 @@ RUN echo "Installing softwares and packages" && \
5563
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
5664
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
5765
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
66+
# copy jupyter configuration
67+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
5868
# Fix permissions to support pip in Openshift environments \
5969
chmod -R g+w /opt/app-root/lib/python3.11/site-packages && \
6070
fix-permissions /opt/app-root -P && \
6171
# Apply JupyterLab addons \
6272
/opt/app-root/bin/utils/addons/apply.sh
63-
73+
6474
WORKDIR /opt/app-root/src
6575

6676
ENTRYPOINT ["start-notebook.sh"]

jupyter/minimal/ubi9-python-3.11/Dockerfile.cuda

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ WORKDIR /opt/app-root/bin
165165

166166
COPY ${JUPYTER_REUSABLE_UTILS} utils/
167167

168+
USER 0
169+
170+
# Dependencies for PDF export
171+
RUN ./utils/install_pdf_deps.sh
172+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
173+
174+
USER 1001
175+
168176
COPY ${MINIMAL_SOURCE_CODE}/Pipfile.lock ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
169177

170178
# Install Python dependencies from Pipfile.lock file
@@ -175,6 +183,8 @@ RUN echo "Installing softwares and packages" && \
175183
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
176184
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
177185
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
186+
# copy jupyter configuration
187+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
178188
# Fix permissions to support pip in Openshift environments \
179189
chmod -R g+w /opt/app-root/lib/python3.11/site-packages && \
180190
fix-permissions /opt/app-root -P && \

jupyter/minimal/ubi9-python-3.11/Dockerfile.rocm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ WORKDIR /opt/app-root/bin
7979

8080
COPY ${JUPYTER_REUSABLE_UTILS} utils/
8181

82+
USER 0
83+
84+
# Dependencies for PDF export
85+
RUN ./utils/install_pdf_deps.sh
86+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
87+
88+
USER 1001
89+
8290
COPY ${MINIMAL_SOURCE_CODE}/Pipfile.lock ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
8391

8492
# Install Python dependencies from Pipfile.lock file
@@ -89,6 +97,8 @@ RUN echo "Installing softwares and packages" && \
8997
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
9098
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
9199
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
100+
# copy jupyter configuration
101+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
92102
# Fix permissions to support pip in Openshift environments \
93103
chmod -R g+w /opt/app-root/lib/python3.11/site-packages && \
94104
fix-permissions /opt/app-root -P && \

jupyter/pytorch/ubi9-python-3.11/Dockerfile.cuda

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ COPY ${JUPYTER_REUSABLE_UTILS} utils/
170170

171171
COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
172172

173+
USER 0
174+
175+
# Dependencies for PDF export
176+
RUN ./utils/install_pdf_deps.sh
177+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
178+
179+
USER 1001
180+
173181
WORKDIR /opt/app-root/src
174182

175183
ENTRYPOINT ["start-notebook.sh"]
@@ -239,6 +247,8 @@ RUN echo "Installing softwares and packages" && \
239247
rm /opt/app-root/share/jupyter/metadata/runtime-images/*.json && \
240248
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
241249
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
250+
# copy jupyter configuration
251+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
242252
# Disable announcement plugin of jupyterlab \
243253
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
244254
# Apply JupyterLab addons \

jupyter/rocm/pytorch/ubi9-python-3.11/Dockerfile.rocm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ COPY ${JUPYTER_REUSABLE_UTILS} utils/
8484

8585
COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
8686

87+
USER 0
88+
89+
# Dependencies for PDF export
90+
RUN ./utils/install_pdf_deps.sh
91+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
92+
93+
USER 1001
94+
8795
WORKDIR /opt/app-root/src
8896

8997
ENTRYPOINT ["start-notebook.sh"]
@@ -153,6 +161,8 @@ RUN echo "Installing softwares and packages" && \
153161
rm /opt/app-root/share/jupyter/metadata/runtime-images/*.json && \
154162
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
155163
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
164+
# copy jupyter configuration
165+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
156166
# Disable announcement plugin of jupyterlab \
157167
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
158168
# Apply JupyterLab addons \

jupyter/rocm/tensorflow/ubi9-python-3.11/Dockerfile.rocm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ WORKDIR /opt/app-root/bin
8282

8383
COPY ${JUPYTER_REUSABLE_UTILS} utils/
8484

85+
USER 0
86+
87+
# Dependencies for PDF export
88+
RUN ./utils/install_pdf_deps.sh
89+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
90+
91+
USER 1001
92+
8593
COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
8694

8795
WORKDIR /opt/app-root/src
@@ -153,6 +161,8 @@ RUN echo "Installing softwares and packages" && \
153161
rm /opt/app-root/share/jupyter/metadata/runtime-images/*.json && \
154162
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
155163
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
164+
# copy jupyter configuration
165+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
156166
# Disable announcement plugin of jupyterlab \
157167
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
158168
# Apply JupyterLab addons \

jupyter/tensorflow/ubi9-python-3.11/Dockerfile.cuda

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ COPY ${JUPYTER_REUSABLE_UTILS} utils/
170170

171171
COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
172172

173+
USER 0
174+
175+
# Dependencies for PDF export
176+
RUN ./utils/install_pdf_deps.sh
177+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
178+
179+
USER 1001
180+
173181
WORKDIR /opt/app-root/src
174182

175183
ENTRYPOINT ["start-notebook.sh"]
@@ -239,6 +247,8 @@ RUN echo "Installing softwares and packages" && \
239247
rm /opt/app-root/share/jupyter/metadata/runtime-images/*.json && \
240248
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
241249
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
250+
# copy jupyter configuration
251+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
242252
# Disable announcement plugin of jupyterlab \
243253
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
244254
# Apply JupyterLab addons \

jupyter/trustyai/ubi9-python-3.11/Dockerfile.cpu

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ WORKDIR /opt/app-root/bin
4949
COPY ${JUPYTER_REUSABLE_UTILS} utils/
5050
COPY ${MINIMAL_SOURCE_CODE}/start-notebook.sh ./
5151

52+
USER 0
53+
54+
# Dependencies for PDF export
55+
RUN ./utils/install_pdf_deps.sh
56+
ENV PATH="/usr/local/texlive/bin/x86_64-linux:/usr/local/pandoc/bin:$PATH"
57+
58+
USER 1001
59+
5260
WORKDIR /opt/app-root/src
5361

5462
ENTRYPOINT ["start-notebook.sh"]
@@ -126,6 +134,8 @@ RUN echo "Installing softwares and packages" && \
126134
rm /opt/app-root/share/jupyter/metadata/runtime-images/*.json && \
127135
# Replace Notebook's launcher, "(ipykernel)" with Python's version 3.x.y \
128136
sed -i -e "s/Python.*/$(python --version | cut -d '.' -f-2)\",/" /opt/app-root/share/jupyter/kernels/python3/kernel.json && \
137+
# copy jupyter configuration
138+
cp /opt/app-root/bin/utils/jupyter_server_config.py /opt/app-root/etc/jupyter && \
129139
# Disable announcement plugin of jupyterlab \
130140
jupyter labextension disable "@jupyterlab/apputils-extension:announcements" && \
131141
# Apply JupyterLab addons \

jupyter/utils/install_pdf_deps.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
# Install dependencies required for Notebooks PDF exports
4+
5+
# tex live installation
6+
echo "Installing TexLive to allow PDf export from Notebooks"
7+
curl -L https://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz -o install-tl-unx.tar.gz
8+
zcat < install-tl-unx.tar.gz | tar xf -
9+
cd install-tl-2*
10+
perl ./install-tl --no-interaction --scheme=scheme-small --texdir=/usr/local/texlive
11+
cd /usr/local/texlive/bin/x86_64-linux
12+
./tlmgr install tcolorbox pdfcol adjustbox titling enumitem soul ucs collection-fontsrecommended
13+
14+
# pandoc installation
15+
curl -L https://github.com/jgm/pandoc/releases/download/3.7.0.2/pandoc-3.7.0.2-linux-amd64.tar.gz -o /tmp/pandoc.tar.gz
16+
mkdir -p /usr/local/pandoc
17+
tar xvzf /tmp/pandoc.tar.gz --strip-components 1 -C /usr/local/pandoc/
18+
rm -f /tmp/pandoc.tar.gz
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# https://github.com/opendatahub-io-contrib/workbench-images/blob/main/snippets/ides/1-jupyter/files/etc/jupyter_notebook_config.py
2+
c = get_config()
3+
# Disable unsupported exporters
4+
c.WebPDFExporter.enabled = False
5+
c.QtPDFExporter.enabled = False
6+
c.QtPNGExporter.enabled = False

scripts/check-payload/config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ error = "ErrNotDynLinked"
250250
files = [
251251
# executable is not dynamically linked
252252
"/opt/app-root/bin/py-spy",
253+
"/usr/local/pandoc/bin/pandoc",
253254
]
254255

255256
[[rpm.code-server.ignore]]

tests/containers/workbenches/jupyterlab/jupyterlab_test.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from __future__ import annotations
22

3+
import pathlib
4+
import tempfile
5+
36
import allure
47
import pytest
58
import requests
@@ -51,6 +54,51 @@ def test_spinner_html_loaded(self, jupyterlab_image: conftest.Image) -> None:
5154
finally:
5255
docker_utils.NotebookContainer(container).stop(timeout=0)
5356

57+
@allure.issue("RHOAIENG-16568")
58+
@allure.description("Check that PDF export is working correctly")
59+
def test_pdf_export(self, jupyterlab_image: conftest.Image) -> None:
60+
container = WorkbenchContainer(image=jupyterlab_image.name, user=4321, group_add=[0])
61+
test_file_name = "test.ipybn"
62+
test_file_content = """{
63+
"cells": [
64+
{
65+
"cell_type": "markdown",
66+
"metadata": {},
67+
"source": [ "# Hello World" ]
68+
},
69+
{
70+
"cell_type": "code",
71+
"execution_count": 1,
72+
"metadata": {},
73+
"outputs": [
74+
{
75+
"name": "stdout",
76+
"output_type": "stream",
77+
"text": [ "Hello World\n" ]
78+
}
79+
],
80+
"source": [ "print('Hello World')" ]
81+
}
82+
],
83+
"metadata": {},
84+
"nbformat": 4,
85+
"nbformat_minor": 5
86+
}
87+
""".replace("\n", "")
88+
try:
89+
container.start(wait_for_readiness=True)
90+
with tempfile.TemporaryDirectory() as tmpdir:
91+
tmpdir = pathlib.Path(tmpdir)
92+
(tmpdir / test_file_name).write_text(test_file_content)
93+
docker_utils.container_cp(
94+
container.get_wrapped_container(), src=str(tmpdir / test_file_name), dst=self.APP_ROOT_HOME
95+
)
96+
exit_code, convert_output = container.exec(["jupyter", "nbconvert", test_file_name, "--to", "pdf"])
97+
assert "PDF successfully created" in convert_output.decode()
98+
assert 0 == exit_code
99+
finally:
100+
docker_utils.NotebookContainer(container).stop(timeout=0)
101+
54102
@allure.issue("RHOAIENG-24348")
55103
@allure.description("Check that custom-built (to be FIPS-compliant) mongocli binary runs.")
56104
def test_mongocli_binary_runs(self, jupyterlab_image: conftest.Image) -> None:

0 commit comments

Comments
 (0)