From 872d956e9663b79a605a69bf906da4f2e15aabec Mon Sep 17 00:00:00 2001 From: "Vazquez,Brais (IT EDP)" Date: Mon, 28 Oct 2024 14:07:54 +0100 Subject: [PATCH] added Jupyter and Rshiny Quickstarters --- .../quickstarters/pages/ds-jupyter-lab.adoc | 81 +++++++++++++++++++ .../quickstarters/pages/ds-rshiny.adoc | 59 ++++++++++++++ ds-jupyter-lab/Jenkinsfile | 32 ++++++++ ds-jupyter-lab/Jenkinsfile.template | 25 ++++++ ds-jupyter-lab/README.md | 7 ++ ds-jupyter-lab/files/.pre-commit-config.yaml | 5 ++ .../files/docker_jupyterlab/Dockerfile | 41 ++++++++++ .../docker_jupyterlab/jupyter_lab_config.json | 9 +++ .../files/docker_jupyterlab/requirements.txt | 3 + ds-jupyter-lab/files/docker_jupyterlab/run.sh | 23 ++++++ ds-jupyter-lab/files/docker_oauth/Dockerfile | 1 + ds-jupyter-lab/files/metadata.yml | 6 ++ ds-jupyter-lab/files/release-manager.yml | 2 + .../testdata/golden/jenkins-build-stages.json | 18 +++++ .../golden/jenkins-provision-stages.json | 26 ++++++ ds-jupyter-lab/testdata/steps.yml | 22 +++++ ds-rshiny/Jenkinsfile | 31 +++++++ ds-rshiny/Jenkinsfile.template | 20 +++++ ds-rshiny/README.md | 7 ++ ds-rshiny/files/.pre-commit-config.yaml | 5 ++ ds-rshiny/files/README.md | 5 ++ ds-rshiny/files/docker_oauth/Dockerfile | 1 + ds-rshiny/files/docker_rshiny/Dockerfile | 65 +++++++++++++++ ds-rshiny/files/docker_rshiny/app.R | 48 +++++++++++ ds-rshiny/files/metadata.yml | 6 ++ ds-rshiny/files/release-manager.yml | 2 + .../testdata/golden/jenkins-build-stages.json | 18 +++++ .../golden/jenkins-provision-stages.json | 26 ++++++ ds-rshiny/testdata/steps.yml | 22 +++++ 29 files changed, 616 insertions(+) create mode 100644 docs/modules/quickstarters/pages/ds-jupyter-lab.adoc create mode 100644 docs/modules/quickstarters/pages/ds-rshiny.adoc create mode 100644 ds-jupyter-lab/Jenkinsfile create mode 100644 ds-jupyter-lab/Jenkinsfile.template create mode 100644 ds-jupyter-lab/README.md create mode 100644 ds-jupyter-lab/files/.pre-commit-config.yaml create mode 100644 ds-jupyter-lab/files/docker_jupyterlab/Dockerfile create mode 100644 ds-jupyter-lab/files/docker_jupyterlab/jupyter_lab_config.json create mode 100644 ds-jupyter-lab/files/docker_jupyterlab/requirements.txt create mode 100644 ds-jupyter-lab/files/docker_jupyterlab/run.sh create mode 100644 ds-jupyter-lab/files/docker_oauth/Dockerfile create mode 100644 ds-jupyter-lab/files/metadata.yml create mode 100644 ds-jupyter-lab/files/release-manager.yml create mode 100644 ds-jupyter-lab/testdata/golden/jenkins-build-stages.json create mode 100644 ds-jupyter-lab/testdata/golden/jenkins-provision-stages.json create mode 100644 ds-jupyter-lab/testdata/steps.yml create mode 100644 ds-rshiny/Jenkinsfile create mode 100644 ds-rshiny/Jenkinsfile.template create mode 100644 ds-rshiny/README.md create mode 100644 ds-rshiny/files/.pre-commit-config.yaml create mode 100644 ds-rshiny/files/README.md create mode 100644 ds-rshiny/files/docker_oauth/Dockerfile create mode 100644 ds-rshiny/files/docker_rshiny/Dockerfile create mode 100644 ds-rshiny/files/docker_rshiny/app.R create mode 100644 ds-rshiny/files/metadata.yml create mode 100644 ds-rshiny/files/release-manager.yml create mode 100644 ds-rshiny/testdata/golden/jenkins-build-stages.json create mode 100644 ds-rshiny/testdata/golden/jenkins-provision-stages.json create mode 100644 ds-rshiny/testdata/steps.yml diff --git a/docs/modules/quickstarters/pages/ds-jupyter-lab.adoc b/docs/modules/quickstarters/pages/ds-jupyter-lab.adoc new file mode 100644 index 0000000..1445fc6 --- /dev/null +++ b/docs/modules/quickstarters/pages/ds-jupyter-lab.adoc @@ -0,0 +1,81 @@ += Data Science Jupyter Lab + +== Purpose of this quickstarter + +Provision a shared Jupyter Lab within OpenShift for rapid prototyping of data science applications using OpenShift OAuth. + +== What files / architecture is generated? + +---- +. +├── Jenkinsfile +├── .pre-commit-config.yaml +├── docker +│ ├── Dockerfile +│ ├── jupyter_lab_config.json +│ ├── requirements.txt +│ └── run.sh +├── metadata.yml - Component metadata +└── release-manager.yml - Configuration file for the Release Manager +---- + +== Frameworks used + +* https://docs.python.org/3.11[Python 3.11] +* https://jupyterlab.readthedocs.io/en/stable/[JupyterLab] + +== Usage - how do you start after you provisioned this quickstarter + +The quickstarter sets up two pods in OpenShift. The `ds-jupyter-lab` instance is routed through the https://github.com/openshift/oauth-proxy/[OpenShift OAuth proxy] instance. + +The directory `/opt/app-root/src/work` is created where code can be organized using installed git. + +Please consider mounting a persistent volume claim for this path. + +New python requirements are specified using the `requirements.txt`. + + +=== Setting up independent environments/kernels === + +One can setup specific and independent IPython kernels based on specific Python virtual environments: + +* Open a new terminal session in your Jupyter Lab, then: + +---- +cd +python -m venv +. /bin/activate +pip install ipykernel pip --upgrade +python -m ipykernel install --user --name= +jupyter kernelspec list # this is for validating installation +---- + +Now on a notebook you can select that new kernel by clicking on the name you see on the top right where you see the dot status. + +=== Metadata + +The following are typical xref:quickstarters:metadata.adoc[metadata] values that can be used for components based on this quickstarter: +Note that the xref:jenkins-shared-library:labelling.adoc[OpenShift resources will be labeled] based on this metadata. + +```yaml +name: jupyterlab +description: "JupyterLab is a web-based interactive development environment for Jupyter notebooks, code, and data." +supplier: https://jupyter.org/ +version: 3.0.14 +type: ods-service +``` + +== How this quickstarter is built through jenkins + +The build pipeline is defined in the `Jenkinsfile` in the project root. The main stages of the pipeline are: + +. Start OpenShift build +. Deploy image to OpenShift + +include::partial$secret-scanning-with-gitleaks.adoc + +== Builder agent used + +https://github.com/opendevstack/ods-core/tree/master/jenkins/agent-base[jenkins-agent-base] + +== Known limitations + +Consider if sufficient computing resources can be provided by the OpenShift cluster. + +You might require installing NodeJS if requiring specific JupyterLab extensions (nodejs >=12.0.0). diff --git a/docs/modules/quickstarters/pages/ds-rshiny.adoc b/docs/modules/quickstarters/pages/ds-rshiny.adoc new file mode 100644 index 0000000..790422b --- /dev/null +++ b/docs/modules/quickstarters/pages/ds-rshiny.adoc @@ -0,0 +1,59 @@ += Data Science R Shiny Application + +== Purpose of this quickstarter + +Provisions a R Shiny application within OpenShift using OpenShift OAuth. + +== What files / architecture is generated? + +---- +. +├── Jenkinsfile - This file contains Jenkins build configuration settings +├── .pre-commit-config.yaml +├── docker - This folder contains Docker configuration settings and main R Shiny app +│ ├── Dockerfile +│ └── app.R +├── metadata.yml - Component metadata +└── release-manager.yml - Configuration file for the Release Manager +---- + +== Frameworks used + +* https://www.tutorialspoint.com/r/index.htm[R] +* https://shiny.rstudio.com/tutorial[Shiny] + +== Usage - how do you start after you provisioned this quickstarter + +The quickstarter sets up two pods in OpenShift. The `ds-rshiny` application is routed through the https://github.com/openshift/oauth-proxy/[OpenShift OAuth proxy] instance. + +=== Metadata + +The following are typical xref:quickstarters:metadata.adoc[metadata] values that can be used for components based on this quickstarter: +Note that the xref:jenkins-shared-library:labelling.adoc[OpenShift resources will be labeled] based on this metadata. + +```yaml +name: shiny +description: "Shiny is an R package that makes it easy to build interactive web apps straight from R." +supplier: https://www.rstudio.com/ +version: 1.6.0 +type: ods-service +runtime: r +runtimeVersion: 4.1.1 +``` + +== How this quickstarter is built through jenkins + +The build pipeline is defined in the `Jenkinsfile` in the project root. The main stages of the pipeline are: + +. Start OpenShift build +. Deploy image to OpenShift + +include::partial$secret-scanning-with-gitleaks.adoc + +== Builder agent used + +https://github.com/opendevstack/ods-core/tree/master/jenkins/agent-base[jenkins-agent-base] + +== Known limitations + +N/A diff --git a/ds-jupyter-lab/Jenkinsfile b/ds-jupyter-lab/Jenkinsfile new file mode 100644 index 0000000..edb7fc0 --- /dev/null +++ b/ds-jupyter-lab/Jenkinsfile @@ -0,0 +1,32 @@ +def odsNamespace = '' +def odsGitRef = '' +def odsImageTag = '' +def sharedLibraryRef = '' +def agentImageTag = '' + +node { + odsNamespace = env.ODS_NAMESPACE ?: 'ods' + odsGitRef = env.ODS_GIT_REF ?: 'master' + odsImageTag = env.ODS_IMAGE_TAG ?: 'latest' + sharedLibraryRef = env.SHARED_LIBRARY_REF ?: odsImageTag + agentImageTag = env.AGENT_IMAGE_TAG ?: odsImageTag +} + +library("ods-jenkins-shared-library@${sharedLibraryRef}") + +odsQuickstarterPipeline( + imageStreamTag: "${odsNamespace}/jenkins-agent-base:${agentImageTag}", +) { context -> + + odsQuickstarterStageCopyFiles(context) + + stage('Setup OpenShift resources') { + sh """sh common/scripts/create-component-with-oauth.sh \ + --project ${context.projectId} \ + --component ${context.componentId} \ + --non-interactive""" + } + + odsQuickstarterStageRenderJenkinsfile(context) + +} diff --git a/ds-jupyter-lab/Jenkinsfile.template b/ds-jupyter-lab/Jenkinsfile.template new file mode 100644 index 0000000..3e4d9cb --- /dev/null +++ b/ds-jupyter-lab/Jenkinsfile.template @@ -0,0 +1,25 @@ +// See https://www.opendevstack.org/ods-documentation/ for usage and customization. + +@Library('ods-jenkins-shared-library@@shared_library_ref@') _ + +odsComponentPipeline( + imageStreamTag: '@ods_namespace@/jenkins-agent-base:@agent_image_tag@', + branchToEnvironmentMapping: [ + 'master': 'dev', + // 'release/': 'test' + ] +) { context -> + + odsComponentStageBuildOpenShiftImage( + context, [ + resourceName: "${context.componentId}", + dockerDir: "docker_jupyterlab", + buildArgs: [ + nexusHostWithBasicAuth: context.nexusHostWithBasicAuth, + nexusHostWithoutScheme: context.nexusHostWithoutScheme + ]]) + odsComponentStageBuildOpenShiftImage( + context, [resourceName: "${context.componentId}-oauth", dockerDir: "docker_oauth"]) + + def deploymentInfo = odsComponentStageRolloutOpenShiftDeployment(context) +} diff --git a/ds-jupyter-lab/README.md b/ds-jupyter-lab/README.md new file mode 100644 index 0000000..42b19b5 --- /dev/null +++ b/ds-jupyter-lab/README.md @@ -0,0 +1,7 @@ +# Jupyter Lab (ds-jupyter-lab) + +Documentation is located in our [official documentation](https://www.opendevstack.org/ods-documentation/ods-quickstarters/latest/index.html) + +Please update documentation in the [antora page directory](https://github.com/opendevstack/ods-quickstarters/tree/master/docs/modules/ROOT/pages) + +Tested thru [automated tests](../tests/ds-jupyter-lab) diff --git a/ds-jupyter-lab/files/.pre-commit-config.yaml b/ds-jupyter-lab/files/.pre-commit-config.yaml new file mode 100644 index 0000000..c9528f4 --- /dev/null +++ b/ds-jupyter-lab/files/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.16.1 + hooks: + - id: gitleaks diff --git a/ds-jupyter-lab/files/docker_jupyterlab/Dockerfile b/ds-jupyter-lab/files/docker_jupyterlab/Dockerfile new file mode 100644 index 0000000..328455c --- /dev/null +++ b/ds-jupyter-lab/files/docker_jupyterlab/Dockerfile @@ -0,0 +1,41 @@ +FROM registry.access.redhat.com/ubi9/python-311 + +ARG nexusHostWithBasicAuth +ARG nexusHostWithoutScheme + +WORKDIR /opt/app-root/src + +ENV PYTHONPATH=$PYTHONPATH:/opt/app-root/src \ + NPM_CONFIG_PREFIX=/opt/app-root \ + NODE_OPTIONS=--max-old-space-size=4096 + +COPY requirements.txt /opt/app-root/src + +USER 1001 +# From load pip install for caching docker build layers +RUN if [ ! -z ${nexusHostWithBasicAuth} ]; \ + then pip install -i ${nexusHostWithBasicAuth}/repository/pypi-all/simple --trusted-host ${nexusHostWithoutScheme} --upgrade pip && pip install -i ${nexusHostWithBasicAuth}/repository/pypi-all/simple --trusted-host ${nexusHostWithoutScheme} -r requirements.txt; \ + else pip install --upgrade pip && pip install -r requirements.txt; \ + fi && \ + pip check + +USER root + +COPY run.sh /opt/app-root/run.sh +COPY jupyter_lab_config.json /opt/app-root/src/.jupyter/jupyter_lab_config.json + +RUN chown -R 1001 /opt/app-root/src && \ + chgrp -R 0 /opt/app-root/src && \ + chmod -R g=u /opt/app-root/src && \ + chmod +x /opt/app-root/run.sh && \ + chmod g+w /etc/passwd && \ + chmod -R g+w /opt/app-root/share && \ + chmod -R g+w /opt/app-root/src + +USER 1001 + +EXPOSE 8080 + +ENTRYPOINT [ "/opt/app-root/run.sh" ] + +CMD [ "jupyter", "lab" ] diff --git a/ds-jupyter-lab/files/docker_jupyterlab/jupyter_lab_config.json b/ds-jupyter-lab/files/docker_jupyterlab/jupyter_lab_config.json new file mode 100644 index 0000000..412ca71 --- /dev/null +++ b/ds-jupyter-lab/files/docker_jupyterlab/jupyter_lab_config.json @@ -0,0 +1,9 @@ +{ + "ServerApp": { + "token": "", + "ip": "0.0.0.0", + "root_dir": "/opt/app-root/src/work", + "port": 8080, + "open_browser": false + } +} diff --git a/ds-jupyter-lab/files/docker_jupyterlab/requirements.txt b/ds-jupyter-lab/files/docker_jupyterlab/requirements.txt new file mode 100644 index 0000000..02e871b --- /dev/null +++ b/ds-jupyter-lab/files/docker_jupyterlab/requirements.txt @@ -0,0 +1,3 @@ +jupyter==1.0.0 +ipywidgets==8.0.6 +jupyterlab==4.0.11 diff --git a/ds-jupyter-lab/files/docker_jupyterlab/run.sh b/ds-jupyter-lab/files/docker_jupyterlab/run.sh new file mode 100644 index 0000000..c45f60e --- /dev/null +++ b/ds-jupyter-lab/files/docker_jupyterlab/run.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +if ! whoami &> /dev/null; then + if [ -w /etc/passwd ]; then + echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:${HOME}:/sbin/nologin" >> /etc/passwd + fi +fi + +# create work directory +mkdir -p /opt/app-root/src/work + +# set the home directories to a folder with read/write access +export XDG_DATA_HOME=/opt/app-root/src +export HOME=/opt/app-root/src + +# link jupyter configs +export JUPYTER_CONFIG_DIR=/opt/app-root/src/.jupyter +export JUPYTER_PATH=/opt/app-root/src/work/.jupyter +export JUPYTER_RUNTIME_DIR=/opt/app-root/src/work/.jupyter/runtime + +exec $@ diff --git a/ds-jupyter-lab/files/docker_oauth/Dockerfile b/ds-jupyter-lab/files/docker_oauth/Dockerfile new file mode 100644 index 0000000..fb57f95 --- /dev/null +++ b/ds-jupyter-lab/files/docker_oauth/Dockerfile @@ -0,0 +1 @@ +FROM registry.redhat.io/openshift4/ose-oauth-proxy:latest diff --git a/ds-jupyter-lab/files/metadata.yml b/ds-jupyter-lab/files/metadata.yml new file mode 100644 index 0000000..3178bf8 --- /dev/null +++ b/ds-jupyter-lab/files/metadata.yml @@ -0,0 +1,6 @@ +--- +name: Jupyter Lab +description: "The Jupyter Lab is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, data visualization, machine learning, and much more. Technologies: JupyterLab 3, Python 3.9" +supplier: https://jupyter.org +version: 4.x +type: ods-service diff --git a/ds-jupyter-lab/files/release-manager.yml b/ds-jupyter-lab/files/release-manager.yml new file mode 100644 index 0000000..23d65c7 --- /dev/null +++ b/ds-jupyter-lab/files/release-manager.yml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/ds-jupyter-lab/testdata/golden/jenkins-build-stages.json b/ds-jupyter-lab/testdata/golden/jenkins-build-stages.json new file mode 100644 index 0000000..441b776 --- /dev/null +++ b/ds-jupyter-lab/testdata/golden/jenkins-build-stages.json @@ -0,0 +1,18 @@ +[ + { + "stage": "odsPipeline start", + "status": "SUCCESS" + }, + { + "stage": "Build OpenShift Image", + "status": "SUCCESS" + }, + { + "stage": "Deploy to OpenShift", + "status": "SUCCESS" + }, + { + "stage": "odsPipeline finished", + "status": "SUCCESS" + } +] diff --git a/ds-jupyter-lab/testdata/golden/jenkins-provision-stages.json b/ds-jupyter-lab/testdata/golden/jenkins-provision-stages.json new file mode 100644 index 0000000..04cb8c2 --- /dev/null +++ b/ds-jupyter-lab/testdata/golden/jenkins-provision-stages.json @@ -0,0 +1,26 @@ +[ + { + "stage": "Checkout quickstarter", + "status": "SUCCESS" + }, + { + "stage": "Initialize output directory", + "status": "SUCCESS" + }, + { + "stage": "Copy files from quickstarter", + "status": "SUCCESS" + }, + { + "stage": "Setup OpenShift resources", + "status": "SUCCESS" + }, + { + "stage": "Create Jenkinsfile", + "status": "SUCCESS" + }, + { + "stage": "Push to remote", + "status": "SUCCESS" + } +] diff --git a/ds-jupyter-lab/testdata/steps.yml b/ds-jupyter-lab/testdata/steps.yml new file mode 100644 index 0000000..533a937 --- /dev/null +++ b/ds-jupyter-lab/testdata/steps.yml @@ -0,0 +1,22 @@ +componentID: jupyter +steps: +- type: provision + provisionParams: + verify: + jenkinsStages: golden/jenkins-provision-stages.json +- type: build + buildParams: + verify: + jenkinsStages: golden/jenkins-build-stages.json + openShiftResources: + imageTags: + - name: "{{.ComponentID}}" + tag: latest + imageStreams: + - "{{.ComponentID}}" + deploymentConfigs: + - "{{.ComponentID}}" + - "{{.ComponentID}}-auth-proxy" + services: + - "{{.ComponentID}}" + - "{{.ComponentID}}-auth-proxy" diff --git a/ds-rshiny/Jenkinsfile b/ds-rshiny/Jenkinsfile new file mode 100644 index 0000000..1a94495 --- /dev/null +++ b/ds-rshiny/Jenkinsfile @@ -0,0 +1,31 @@ +def odsNamespace = '' +def odsGitRef = '' +def odsImageTag = '' +def sharedLibraryRef = '' +def agentImageTag = '' + +node { + odsNamespace = env.ODS_NAMESPACE ?: 'ods' + odsGitRef = env.ODS_GIT_REF ?: 'master' + odsImageTag = env.ODS_IMAGE_TAG ?: 'latest' + sharedLibraryRef = env.SHARED_LIBRARY_REF ?: odsImageTag + agentImageTag = env.AGENT_IMAGE_TAG ?: odsImageTag +} + +library("ods-jenkins-shared-library@${sharedLibraryRef}") + +odsQuickstarterPipeline( + imageStreamTag: "${odsNamespace}/jenkins-agent-base:${agentImageTag}", +) { context -> + + odsQuickstarterStageCopyFiles(context) + + stage('Setup OpenShift resources') { + sh """sh common/scripts/create-component-with-oauth.sh \ + --project ${context.projectId} \ + --component ${context.componentId} \ + --non-interactive""" + } + + odsQuickstarterStageRenderJenkinsfile(context) +} diff --git a/ds-rshiny/Jenkinsfile.template b/ds-rshiny/Jenkinsfile.template new file mode 100644 index 0000000..9c6a266 --- /dev/null +++ b/ds-rshiny/Jenkinsfile.template @@ -0,0 +1,20 @@ +// See https://www.opendevstack.org/ods-documentation/ for usage and customization. + +@Library('ods-jenkins-shared-library@@shared_library_ref@') _ + +odsComponentPipeline( + imageStreamTag: '@ods_namespace@/jenkins-agent-base:@agent_image_tag@', + openshiftBuildTimeout: 30, + branchToEnvironmentMapping: [ + 'master': 'dev', + // 'release/': 'test' + ] +) { context -> + + odsComponentStageBuildOpenShiftImage( + context, [resourceName: "${context.componentId}", dockerDir: "docker_rshiny"]) + odsComponentStageBuildOpenShiftImage( + context, [resourceName: "${context.componentId}-oauth", dockerDir: "docker_oauth"]) + + def deploymentInfo = odsComponentStageRolloutOpenShiftDeployment(context) +} diff --git a/ds-rshiny/README.md b/ds-rshiny/README.md new file mode 100644 index 0000000..4449321 --- /dev/null +++ b/ds-rshiny/README.md @@ -0,0 +1,7 @@ +# R-Shiny Notebook (ds-rshiny) + +Documentation is located in our [official documentation](https://www.opendevstack.org/ods-documentation/ods-quickstarters/latest/index.html) + +Please update documentation in the [antora page directory](https://github.com/opendevstack/ods-quickstarters/tree/master/docs/modules/ROOT/pages) + +Tested thru [automated tests](../tests/ds-rshiny) diff --git a/ds-rshiny/files/.pre-commit-config.yaml b/ds-rshiny/files/.pre-commit-config.yaml new file mode 100644 index 0000000..c9528f4 --- /dev/null +++ b/ds-rshiny/files/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.16.1 + hooks: + - id: gitleaks diff --git a/ds-rshiny/files/README.md b/ds-rshiny/files/README.md new file mode 100644 index 0000000..b765482 --- /dev/null +++ b/ds-rshiny/files/README.md @@ -0,0 +1,5 @@ +# Rshiny Application + +Documentation is located in our [official documentation](https://www.opendevstack.org/ods-documentation/ods-quickstarters/latest/index.html) + +Please update documentation in the [antora page directory](https://github.com/opendevstack/ods-quickstarters/tree/master/docs/modules/ROOT/pages) diff --git a/ds-rshiny/files/docker_oauth/Dockerfile b/ds-rshiny/files/docker_oauth/Dockerfile new file mode 100644 index 0000000..fb57f95 --- /dev/null +++ b/ds-rshiny/files/docker_oauth/Dockerfile @@ -0,0 +1 @@ +FROM registry.redhat.io/openshift4/ose-oauth-proxy:latest diff --git a/ds-rshiny/files/docker_rshiny/Dockerfile b/ds-rshiny/files/docker_rshiny/Dockerfile new file mode 100644 index 0000000..083ca54 --- /dev/null +++ b/ds-rshiny/files/docker_rshiny/Dockerfile @@ -0,0 +1,65 @@ +FROM ubuntu:20.04 + +ENV DEBIAN_FRONTEND noninteractive +ENV INITRD No +ENV LANGUAGE en +ENV LC_ALL en_US.UTF-8 +ENV LANG en_US.UTF-8 + +# Dockerize container and setup required OS dependencies +RUN echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/02apt-speedup && \ + echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' > /etc/apt/apt.conf.d/00no-cache && \ + /usr/bin/dpkg-divert --local --rename --add /usr/bin/ischroot && \ + rm -f /usr/bin/ischroot && \ + ln -s /bin/true /usr/bin/ischroot && \ + /usr/bin/dpkg-divert --local --rename --add /sbin/initctl && \ + rm -f /sbin/initctl && \ + ln -s /bin/true /sbin/initctl && \ + # Setup locales + apt-get update && \ + apt-get install -yqq locales apt-transport-https ca-certificates gnupg && \ + /usr/sbin/locale-gen en_US.UTF-8 && \ + /usr/sbin/update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 && \ + # Add CRAN apt repo / focal (Ubuntu 20.04) R/4.0 + if [ -n "$HTTP_PROXY" ]; then \ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options http-proxy=$HTTP_PROXY --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9; \ + else \ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9; \ + fi && \ + echo 'deb https://cloud.r-project.org/bin/linux/ubuntu focal-cran40/' > /etc/apt/sources.list.d/cran.list && \ + # Install dependencies + apt-get update && \ + apt-get install -yqq \ + gdebi-core \ + libcairo2-dev \ + libcurl4-gnutls-dev \ + libxt-dev \ + pandoc \ + pandoc-citeproc \ + libssl-dev && \ + apt-get install -yqq \ + r-base \ + r-base-core \ + r-recommended \ + r-base-dev && \ + # Cleanup apt + apt-get autoremove --purge && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /var/cache/apt/archives + +# Install Shiny +RUN R -e 'install.packages(c("shiny", "rmarkdown"), repos="https://cloud.r-project.org/")' + +# Install app dependencies and fail if any missing +RUN R -e 'packages = c("shinythemes", "ggplot2", "reshape2"); \ + install.packages(packages, repos="https://cloud.r-project.org/"); \ + package.check <- lapply(packages, FUN = function(p) { if(!require(p, character.only = TRUE)) { stop("package not found!") } })' + +# Setup app +RUN mkdir /app +WORKDIR /app +ADD app.R /app +EXPOSE 8080 + +# Run app +CMD ["R", "--quiet", "--no-save", "--no-restore", "-e", "setwd('/app'); shiny::runApp(appDir='.', port=8080, host='0.0.0.0', quiet=F, display.mode='normal')"] diff --git a/ds-rshiny/files/docker_rshiny/app.R b/ds-rshiny/files/docker_rshiny/app.R new file mode 100644 index 0000000..268c8c8 --- /dev/null +++ b/ds-rshiny/files/docker_rshiny/app.R @@ -0,0 +1,48 @@ +library(shiny) +library(shinythemes) +library(ggplot2) +library(reshape2) + +# ================================================= UI PART ======================================================= +ui <- fluidPage( + + # Application title + titlePanel("Hello Shiny!"), + + # Sidebar with a slider input for number of observations + sidebarLayout( + sidebarPanel( + sliderInput("obs", + "Number of observations:", + min = 1, + max = 1000, + value = 500) + ), + + # Show a plot of the generated distribution + mainPanel( + plotOutput("distPlot") + ) + ) +) + +# ====================================== SERVER PART ======================================================= +server <- function(input, output) { + + # Expression that generates a plot of the distribution. The expression + # is wrapped in a call to renderPlot to indicate that: + # + # 1) It is "reactive" and therefore should be automatically + # re-executed when inputs change + # 2) Its output type is a plot + # + output$distPlot <- renderPlot({ + + # generate an rnorm distribution and plot it + dist <- rnorm(input$obs) + hist(dist) + }) + +} + +shinyApp(ui, server) diff --git a/ds-rshiny/files/metadata.yml b/ds-rshiny/files/metadata.yml new file mode 100644 index 0000000..9859422 --- /dev/null +++ b/ds-rshiny/files/metadata.yml @@ -0,0 +1,6 @@ +--- +name: R Shiny +description: "Shiny is an R package that makes it easy to build interactive web apps straight from R. Technologies: R Shiny unpinned" +supplier: https://shiny.rstudio.com +version: 4.x +type: ods-service diff --git a/ds-rshiny/files/release-manager.yml b/ds-rshiny/files/release-manager.yml new file mode 100644 index 0000000..23d65c7 --- /dev/null +++ b/ds-rshiny/files/release-manager.yml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/ds-rshiny/testdata/golden/jenkins-build-stages.json b/ds-rshiny/testdata/golden/jenkins-build-stages.json new file mode 100644 index 0000000..441b776 --- /dev/null +++ b/ds-rshiny/testdata/golden/jenkins-build-stages.json @@ -0,0 +1,18 @@ +[ + { + "stage": "odsPipeline start", + "status": "SUCCESS" + }, + { + "stage": "Build OpenShift Image", + "status": "SUCCESS" + }, + { + "stage": "Deploy to OpenShift", + "status": "SUCCESS" + }, + { + "stage": "odsPipeline finished", + "status": "SUCCESS" + } +] diff --git a/ds-rshiny/testdata/golden/jenkins-provision-stages.json b/ds-rshiny/testdata/golden/jenkins-provision-stages.json new file mode 100644 index 0000000..04cb8c2 --- /dev/null +++ b/ds-rshiny/testdata/golden/jenkins-provision-stages.json @@ -0,0 +1,26 @@ +[ + { + "stage": "Checkout quickstarter", + "status": "SUCCESS" + }, + { + "stage": "Initialize output directory", + "status": "SUCCESS" + }, + { + "stage": "Copy files from quickstarter", + "status": "SUCCESS" + }, + { + "stage": "Setup OpenShift resources", + "status": "SUCCESS" + }, + { + "stage": "Create Jenkinsfile", + "status": "SUCCESS" + }, + { + "stage": "Push to remote", + "status": "SUCCESS" + } +] diff --git a/ds-rshiny/testdata/steps.yml b/ds-rshiny/testdata/steps.yml new file mode 100644 index 0000000..a46c5ff --- /dev/null +++ b/ds-rshiny/testdata/steps.yml @@ -0,0 +1,22 @@ +componentID: rshiny +steps: +- type: provision + provisionParams: + verify: + jenkinsStages: golden/jenkins-provision-stages.json +- type: build + buildParams: + verify: + jenkinsStages: golden/jenkins-build-stages.json + openShiftResources: + imageTags: + - name: "{{.ComponentID}}" + tag: latest + imageStreams: + - "{{.ComponentID}}" + deploymentConfigs: + - "{{.ComponentID}}" + - "{{.ComponentID}}-auth-proxy" + services: + - "{{.ComponentID}}" + - "{{.ComponentID}}-auth-proxy"