diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 79f586e5636e5c9435ba33ab92b52470c30aee54..fd8d8e9f743aead48dfb49e590f42fe303e3fb9b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,17 +14,22 @@ stages: STORAGE_DRIVER: vfs BUILDAH_FORMAT: docker BUILDAH_ISOLATION: chroot - FQ_IMAGE_NAME: "$CI_REGISTRY_IMAGE/front:$CI_COMMIT_SHORT_SHA" + IMAGE_NAME: front + IMAGE_TAG: "$CI_COMMIT_SHORT_SHA" + REGISTRY_IMAGE: "$CI_REGISTRY_IMAGE/$IMAGE_NAME" + FQ_IMAGE_NAME: "$REGISTRY_IMAGE:$IMAGE_TAG" BUILD_CONTEXT: "." CONTAINERFILE: "front/Containerfile" before_script: - export REGISTRY_AUTH_FILE="$HOME/auth.json" - echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY" script: - - buildah build -t "$FQ_IMAGE_NAME" -f "$CONTAINERFILE" "$BUILD_CONTEXT" + - buildah build -t "$FQ_IMAGE_NAME" -f "$CONTAINERFILE" $BUILD_CONTEXT - buildah push "$FQ_IMAGE_NAME" + - buildah tag "$FQ_IMAGE_NAME" "$REGISTRY_IMAGE:latest" + - buildah push "$REGISTRY_IMAGE:latest" -build on gitlab.pasteur.fr: +build front: extends: .build-with-buildah variables: PUBLIC_URL: "nyx.pasteur.cloud" @@ -32,7 +37,7 @@ build on gitlab.pasteur.fr: - if: ($CI_COMMIT_BRANCH == "main" && $CI_PROJECT_ID == $GITLAB_PASTEUR_PROJECT_ID) # gitlab.pasteur.fr only -build dev on gitlab.pasteur.fr: +build dev front: extends: .build-with-buildah variables: PUBLIC_URL: "nyx.dev.pasteur.cloud" @@ -40,25 +45,6 @@ build dev on gitlab.pasteur.fr: - if: ($CI_COMMIT_BRANCH == "dev" && $CI_PROJECT_ID == $GITLAB_PASTEUR_PROJECT_ID) # gitlab.pasteur.fr only -.deploy-with-manifests: - stage: deploy - image: docker.io/enix/ci-toolbox:1.21 - variables: - APP_NAME: nyxui - FQ_IMAGE_NAME: "$CI_REGISTRY_IMAGE/front:$CI_COMMIT_SHORT_SHA" - script: - - kubectl create secret - docker-registry registry-gitlab - --docker-server=registry-gitlab.pasteur.fr - --docker-username="$DOCKER_USER" - --docker-password="$DOCKER_TOKEN" - --docker-email=kubernetes@pasteur.fr - -n "$KUBE_NAMESPACE" - --dry-run=client -o yaml | kubectl apply -f - - - envsubst < k8s/front-deployment.yaml | kubectl apply -n "$KUBE_NAMESPACE" -f - - - envsubst < k8s/front-service.yaml | kubectl apply -n "$KUBE_NAMESPACE" -f - - - envsubst < k8s/ingress.yaml | kubectl apply -n "$KUBE_NAMESPACE" -f - - .deploy-with-helm: stage: deploy image: docker.io/enix/ci-toolbox:1.21 @@ -81,16 +67,17 @@ build dev on gitlab.pasteur.fr: deploy to pasteur.cloud: extends: .deploy-with-helm variables: - SERVICE_TARGET_PORT: "8080" IMAGE_SECRETS: "registry-gitlab" KUBE_NAMESPACE: "nyx-prod" PUBLIC_URL: "nyx.pasteur.cloud" INGRESS_CLASS: "external" INGRESS_URL: "nyx.pasteur.cloud" - SERVICE_PORT: "80" LIMITS_CPU: "2" - LIMITS_MEMORY: "4Gi" - LIMITS_STORAGE: "1Gi" + LIMITS_MEMORY: "5Gi" + LIMITS_STORAGE: "4Gi" + LT_LIMITS_CPU: "2" + LT_LIMITS_MEMORY: "5Gi" + LT_LIMITS_STORAGE: "2Gi" environment: name: k8sprod-02/nyx-prod url: https://nyx.pasteur.cloud @@ -102,16 +89,17 @@ deploy to pasteur.cloud: deploy to dev.pasteur.cloud: extends: .deploy-with-helm variables: - SERVICE_TARGET_PORT: "8080" IMAGE_SECRETS: "registry-gitlab" KUBE_NAMESPACE: "nyx-dev" PUBLIC_URL: "nyx.dev.pasteur.cloud" INGRESS_CLASS: "internal" INGRESS_URL: "nyx.dev.pasteur.cloud" - SERVICE_PORT: "80" LIMITS_CPU: "2" - LIMITS_MEMORY: "4Gi" - LIMITS_STORAGE: "1Gi" + LIMITS_MEMORY: "5Gi" + LIMITS_STORAGE: "4Gi" + LT_LIMITS_CPU: "2" + LT_LIMITS_MEMORY: "5Gi" + LT_LIMITS_STORAGE: "2Gi" environment: name: k8sdev-01/nyx-dev url: https://nyx.dev.pasteur.cloud @@ -120,3 +108,16 @@ deploy to dev.pasteur.cloud: $CI_PROJECT_ID == $GITLAB_PASTEUR_PROJECT_ID) # gitlab.pasteur.fr only when: manual +build larvatagger backend: + extends: .build-with-buildah + variables: + IMAGE_NAME: "larvatagger" + IMAGE_TAG: "0.20.1-bigfat" + BUILD_CONTEXT: --build-arg LARVATAGGER_IMAGE_TAG=0.20.1-bigfat back + CONTAINERFILE: "back/Containerfile.larvatagger" + rules: + - if: ($CI_COMMIT_BRANCH == "dev" && + $CI_PROJECT_ID == $GITLAB_PASTEUR_PROJECT_ID) # gitlab.pasteur.fr only + when: manual # on IMAGE_TAG update only; alias latest is used and + allow_failure: true # should be confirmed to work when moving to branch main + diff --git a/Project.toml b/Project.toml index c0988dd6a547e0f579a517e251b1c385ea5b8d2f..d4e91c2a9b2074c33ffa2c1b18d2e0d50a339547 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "NyxUI" uuid = "2c32e805-e4ca-4d0f-96f6-9d2d6204339d" authors = ["François Laurent <francois.laurent@pasteur.fr>"] -version = "0.2.0" +version = "0.2.1" [deps] Bonito = "824d6782-a2ef-11e9-3a09-e5662e0c26f8" diff --git a/README.md b/README.md index 4b6613d49b827be7f5327db4ddfc1184f91a04a3..f97582dddea39d74bb78cd820274f18fc7640eee 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Web interface meant to be served at [nyx.pasteur.cloud](https://nyx.pasteur.clou It features an app catalog, with the following apps: * an editor for muscular activity programs, -* [LarvaTagger.jl](https://gitlab.pasteur.fr/nyx/larvatagger.jl) without any automating tagging backends. +* [LarvaTagger.jl](https://gitlab.pasteur.fr/nyx/larvatagger.jl) with two automating tagging backends. ## Local installation @@ -24,10 +24,11 @@ cp front/Manifest.toml . juliaup add lts juliaup default lts julia --project=. -e 'using Pkg; Pkg.instantiate()' +. back/larvatagger-no-build.sh julia --project=. routes.jl ``` -You may be asked whether to authorize ports 9284 and 9285; please give the app permission. +You may be asked whether to authorize ports 9284, 9285 and 9286; please give the app permission. From there, in a web browser, open http://localhost:9284/ to access the app. @@ -35,4 +36,9 @@ Note that the generated files can be found somewhere in directory *storage/expor The download buttons in the LarvaTagger app will not work in the web browser. To make them work, the reverse proxy setup in the container image called *front* is required. -If you have [Podman](https://podman.io/), as an alternative to the above installation procedure, you can simply run `front/build.sh --now` and, once the container is up and running, connect to http://localhost:8080/. +If you have [Podman](https://podman.io/), as an alternative to the above installation procedure, you can simply run the backend and frontend as follows: +``` +. back/larvatagger-no-build.sh +front/build.sh --now +``` +Once the frontend container is up and running, connect to http://localhost:8080/. diff --git a/back/Containerfile.larvatagger b/back/Containerfile.larvatagger new file mode 100644 index 0000000000000000000000000000000000000000..963f0428d1ff978e2996a9348ba71be7a44123ac --- /dev/null +++ b/back/Containerfile.larvatagger @@ -0,0 +1,58 @@ +ARG LARVATAGGER_IMAGE_TAG=0.20.1-bigfat +FROM docker.io/flaur/larvatagger:${LARVATAGGER_IMAGE_TAG} as src + + +FROM debian:bullseye as base + +# Python and Curl for Poetry +RUN apt-get update \ + && apt-get install --no-install-recommends -y python3-dev python3-pip curl \ + && rm -rf /var/lib/apt/lists/* + +# Unprivileged environment +ARG UID=1001 + +RUN useradd julia -u ${UID} --user-group --create-home + +COPY --chown=julia --from=src /app /app/ + +USER ${UID} + +# Poetry +ENV POETRY_VERSION=1.8.4 + +ENV POETRY_HOME=/app/poetry +ENV POETRY_VIRTUALENVS_IN_PROJECT=1 +ENV PIP_DISABLE_PIP_VERSION_CHECK=1 +ENV PIP_NO_CACHE_DIR=1 + +RUN curl -sSL https://install.python-poetry.org | python3 - + +# Julia +ARG JULIA_VERSION=1.10.9 + +ENV JULIA_PROJECT=/app +ENV JULIA_DEPOT_PATH=/app/julia +ENV JULIAUP_DEPOT_PATH=/app/juliaup + +RUN export HOME="${JULIA_PROJECT}" \ + && curl -fsSL https://install.julialang.org \ + | sh -s -- --yes --default-channel "${JULIA_VERSION}" \ + && ${JULIA_PROJECT}/.juliaup/bin/juliaup config versionsdbupdateinterval 0 + +ENV PATH "${PATH}:${JULIA_PROJECT}/.juliaup/bin:${POETRY_HOME}/bin" + +# LarvaTagger.jl/MaggotUBA-adapter/PasteurJanelia-adapter +RUN cd "${JULIA_PROJECT}" \ + && julia -e 'using Pkg; Pkg.instantiate()' \ + && cd MaggotUBA \ + && poetry install --only main \ + && cd ../PasteurJanelia \ + && poetry install --only main + +# final stage + +COPY --chown=julia larvatagger-entrypoint.sh /app/ + +ENTRYPOINT ["/app/larvatagger-entrypoint.sh"] +CMD [] diff --git a/back/larvatagger-build.sh b/back/larvatagger-build.sh new file mode 100755 index 0000000000000000000000000000000000000000..dcbdefd4efd44f8c70416a87a345be5e1be2c282 --- /dev/null +++ b/back/larvatagger-build.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +CONTAINERFILE=back/Containerfile.larvatagger + +if ! [ -f "$CONTAINERFILE" -a -f routes.jl ]; then + echo "Run $0 from the project root directory" + exit 1 +fi + +IMAGE=larvatagger-backend + +podman rmi -f $IMAGE || true + +podman build --tag $IMAGE -f "$CONTAINERFILE" back + +if [ "$1" = "--now" ]; then + podman run -d -p 9286:9286 $IMAGE + + CONTAINER=`podman ps | grep $IMAGE | cut -d' ' -f1` + + if [ -n "$CONTAINER" ]; then + echo "podman logs -f $CONTAINER" + sleep 1 + podman logs -f $CONTAINER + fi +fi + +export LARVATAGGER_BACKEND=http://localhost:9286 diff --git a/back/larvatagger-entrypoint.sh b/back/larvatagger-entrypoint.sh new file mode 100755 index 0000000000000000000000000000000000000000..aa3148262e7ecbd5645582d987dbc231d0ad3486 --- /dev/null +++ b/back/larvatagger-entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +if [ -z "$LARVATAGGER_PORT" ]; then + LARVATAGGER_PORT=9286 +else + echo "Using environment variable: LARVATAGGER_PORT= $LARVATAGGER_PORT" +fi + +if [ -z "$LARVATAGGER_TOKEN_EXPIRY" ]; then + LARVATAGGER_TOKEN_EXPIRY=14400 +else + echo "Using environment variable: LARVATAGGER_TOKEN_EXPIRY= $LARVATAGGER_TOKEN_EXPIRY" +fi + +julia -e "using LarvaTagger.REST.Server; run_backend(\"/app\", $LARVATAGGER_TOKEN_EXPIRY; host=\"0.0.0.0\", port=$LARVATAGGER_PORT)" diff --git a/back/larvatagger-no-build.sh b/back/larvatagger-no-build.sh new file mode 100755 index 0000000000000000000000000000000000000000..7101dd78a518d69cc5900982cd093c28b29184bc --- /dev/null +++ b/back/larvatagger-no-build.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# for tests with lightweight deployment + +if [ -z "$LARVATAGGER_PORT" ]; then + LARVATAGGER_PORT=9286 +else + echo "Using environment variable: LARVATAGGER_PORT= $LARVATAGGER_PORT" +fi +if [ -z "$LARVATAGGER_IMAGE" ]; then + LARVATAGGER_IMAGE=docker.io/flaur/larvatagger:0.20-bigfat +else + echo "Using environment variable: LARVATAGGER_IMAGE= $LARVATAGGER_IMAGE" +fi +if [ -z "$LARVATAGGER_TOKEN_EXPIRY" ]; then + LARVATAGGER_TOKEN_EXPIRY=3600 +else + echo "Using environment variable: LARVATAGGER_TOKEN_EXPIRY= $LARVATAGGER_TOKEN_EXPIRY" +fi + +podman run -d -p $LARVATAGGER_PORT:9285 --entrypoint=julia $LARVATAGGER_IMAGE --project=/app \ + -e "using LarvaTagger.REST.Server; run_backend(\"/app\", $LARVATAGGER_TOKEN_EXPIRY; host=\"0.0.0.0\")" + +CONTAINER=`podman ps | grep $LARVATAGGER_IMAGE | cut -d' ' -f1` +if ! [ -z "$CONTAINER" ]; then + echo "To monitor the LarvaTagger backend:" + echo "podman logs -f $CONTAINER" +fi + +export LARVATAGGER_BACKEND=http://localhost:$LARVATAGGER_PORT diff --git a/front/Containerfile b/front/Containerfile index ca3adb2ca753e1ccc03e122f5601699f51eaeb6d..c788eb393e2502007750241730379d6f33192c04 100644 --- a/front/Containerfile +++ b/front/Containerfile @@ -16,7 +16,7 @@ ENV JULIA_PROJECT /app ENV JULIA_DEPOT_PATH /app/julia ENV JULIAUP_DEPOT_PATH /app/juliaup -ARG JULIA_VERSION=1.10.8 +ARG JULIA_VERSION=1.10.9 # UID/GID should match with same arguments defined in: # https://github.com/nginxinc/docker-nginx-unprivileged/blob/main/mainline/debian/Dockerfile diff --git a/front/Containerfile.local b/front/Containerfile.local index 1449a18a07a320562569f5b34085d88edbb3e1ea..d25b8dc6c2da4c909e9ce01c4b12d912aed9a010 100644 --- a/front/Containerfile.local +++ b/front/Containerfile.local @@ -6,7 +6,7 @@ COPY ./NyxUI.jl/front/proxy.conf /etc/nginx/conf.d/default.conf ENV JULIAUP_DEPOT_PATH /juliaup ENV JULIA_DEPOT_PATH /julia -ARG JULIA_VERSION=1.10.8 +ARG JULIA_VERSION=1.10.9 RUN curl -fsSL https://install.julialang.org \ | sh -s -- --yes --default-channel $JULIA_VERSION diff --git a/front/Manifest.toml b/front/Manifest.toml index 7b87bea4414da2f15a4abc08c99fb472c32226cf..c55bc77741b68794a3f25a3b962a0272af08f286 100644 --- a/front/Manifest.toml +++ b/front/Manifest.toml @@ -1,6 +1,6 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.10.8" +julia_version = "1.10.9" manifest_format = "2.0" project_hash = "f30a6bd140cd9f9b66d3656725e83b8d83e18ee6" @@ -833,12 +833,12 @@ uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" version = "1.4.0" [[deps.LarvaTagger]] -deps = ["Bonito", "Colors", "Dates", "DocOpt", "Format", "LinearAlgebra", "Logging", "Makie", "Meshes", "NearestNeighbors", "NyxWidgets", "Observables", "ObservationPolicies", "OrderedCollections", "PlanarLarvae", "Random", "StaticArrays", "Statistics", "TidyObservables", "WGLMakie"] -git-tree-sha1 = "c9c185beb0bf417ed98afe9b8b9da557a0b886b7" +deps = ["Bonito", "Colors", "Dates", "DocOpt", "Format", "HTTP", "JSON3", "LinearAlgebra", "Logging", "Makie", "Meshes", "NearestNeighbors", "NyxWidgets", "Observables", "ObservationPolicies", "OrderedCollections", "Oxygen", "PlanarLarvae", "Random", "StaticArrays", "Statistics", "TidyObservables", "WGLMakie"] +git-tree-sha1 = "0b405b69b603ef4df736142907a32ab81df20215" repo-rev = "main" repo-url = "https://gitlab.pasteur.fr/nyx/larvatagger.jl" uuid = "8b3b36f1-dfed-446e-8561-ea19fe966a4d" -version = "0.19.1" +version = "0.20.1" [[deps.LazyArtifacts]] deps = ["Artifacts", "Pkg"] @@ -1182,7 +1182,7 @@ version = "3.2.4+0" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+2" +version = "0.8.1+4" [[deps.OpenMPI_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML", "Zlib_jll"] @@ -1219,6 +1219,12 @@ git-tree-sha1 = "12f1439c4f986bb868acda6ea33ebc78e19b95ad" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" version = "1.7.0" +[[deps.Oxygen]] +deps = ["DataStructures", "Dates", "HTTP", "JSON3", "MIMEs", "Reexport", "RelocatableFolders", "Requires", "Sockets", "Statistics", "StructTypes"] +git-tree-sha1 = "2ad010b0de6172faf1d09ed5e0837eb0b7355bd8" +uuid = "df9a0d86-3283-4920-82dc-4555fc0d1d8b" +version = "1.5.16" + [[deps.PCRE2_jll]] deps = ["Artifacts", "Libdl"] uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" diff --git a/front/build-run-local.sh b/front/build-run-local.sh index 79c9f43c516b343ebe6ad3c278c5d3cd2efc4a21..3aeaf2cf5830e21d597b2c1020197a569d04638d 100755 --- a/front/build-run-local.sh +++ b/front/build-run-local.sh @@ -18,7 +18,7 @@ podman build --tag $IMAGE -f "$CONTAINERFILE" .. # --no-cache #mkdir -p public podman run -d -p 8081:80 -p 9484:9284 -p 9485:9285 \ - $IMAGE + -e LARVATAGGER_BACKEND $IMAGE CONTAINER=`podman ps | grep $IMAGE | cut -d' ' -f1` diff --git a/front/build.sh b/front/build.sh index 02619d93707323be1424da296f75d23b03c4f9ee..1b9693e7604222abb0d8f84078505bb916cc64ba 100755 --- a/front/build.sh +++ b/front/build.sh @@ -14,7 +14,7 @@ podman rmi -f $IMAGE || true podman build --tag $IMAGE -f "$CONTAINERFILE" . if [ "$1" = "--now" ]; then - podman run -d -p 8080:8080 $IMAGE + podman run -d -p 8080:8080 -e LARVATAGGER_BACKEND $IMAGE CONTAINER=`podman ps | grep $IMAGE | cut -d' ' -f1` diff --git a/front/entrypoint.sh b/front/entrypoint.sh index ae9288c705d3be255e713840b01b6dda44475ac1..035824383afd539fbaf57417a5c0d6380ba9c982 100644 --- a/front/entrypoint.sh +++ b/front/entrypoint.sh @@ -2,6 +2,17 @@ set -m +cd /app + +if [ -f "front/.env" ]; then + echo "Found dotenv file:" + echo "------------------" + cat front/.env + echo "------------------" + export `cat front/.env | xargs` +fi +LARVATAGGER_BACKEND=`echo $LARVATAGGER_BACKEND | sed "s/localhost/host.containers.internal/"` + /docker-entrypoint.sh nginx -g "daemon off;" &>/dev/null & NGINX_PID=$! diff --git a/nyxui/Chart.yaml b/nyxui/Chart.yaml index 567ea86302b3a01ca09c28aa9ff20c3b221acfe9..0126bd73d2b6b45bfc01440c03ffad743acd82c3 100644 --- a/nyxui/Chart.yaml +++ b/nyxui/Chart.yaml @@ -15,10 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.0 +version: 0.2.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.2.0" +appVersion: "0.2.1" diff --git a/nyxui/templates/configmap-front.yaml b/nyxui/templates/configmap-front.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5505c88ba7f881e8cd9edbba2840e5e50e33ffdc --- /dev/null +++ b/nyxui/templates/configmap-front.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "nyxui.name" . }}-front-config + labels: + {{- include "nyxui.labels" . | nindent 4 }} +data: + .env: | + LARVATAGGER_BACKEND=http://{{ include "nyxui.name" . }}-larvatagger:{{ .Values.service.port }} diff --git a/nyxui/templates/deployment-front.yaml b/nyxui/templates/deployment-front.yaml index e4319b60f95077b28ca3c82ebbb063a4c36914a9..d54718c230320e9a2b843afca2e5c0ca43c6f36e 100644 --- a/nyxui/templates/deployment-front.yaml +++ b/nyxui/templates/deployment-front.yaml @@ -1,7 +1,7 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "nyxui.name" . }} + name: {{ include "nyxui.name" . }}-front labels: {{- include "nyxui.labels" . | nindent 4 }} spec: @@ -19,6 +19,7 @@ spec: {{- end }} labels: {{- include "nyxui.labels" . | nindent 8 }} + app.kubernetes.io/component: front {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }} @@ -45,13 +46,19 @@ spec: readinessProbe: {{- toYaml .Values.readinessProbe | nindent 12 }} resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.volumeMounts }} + {{- toYaml .Values.front.resources | nindent 12 }} volumeMounts: + - name: front-config + mountPath: /app/front/.env + subPath: .env + {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} - {{- with .Values.volumes }} volumes: + - name: front-config + configMap: + name: nyxui-front-config + {{- with .Values.volumes }} {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.nodeSelector }} diff --git a/nyxui/templates/deployment-larvatagger.yaml b/nyxui/templates/deployment-larvatagger.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e47504b514bb3111a860a6f4d322d3fd91fe7e7f --- /dev/null +++ b/nyxui/templates/deployment-larvatagger.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "nyxui.name" . }}-larvatagger + labels: + {{- include "nyxui.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "nyxui.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "nyxui.labels" . | nindent 8 }} + app.kubernetes.io/component: larvatagger + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "nyxui.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.larvatagger.image.repository }}/{{ .Values.larvatagger.image.name }}:{{ .Values.larvatagger.image.tag }}" + imagePullPolicy: {{ .Values.larvatagger.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.larvatagger.service.targetPort }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.larvatagger.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/nyxui/templates/ingress.yaml b/nyxui/templates/ingress.yaml index 79522d81581951e662142e67a07a2f658f1dbbc0..03b430ca4f4babe57d49441578a6e7c74322f7f3 100644 --- a/nyxui/templates/ingress.yaml +++ b/nyxui/templates/ingress.yaml @@ -49,11 +49,11 @@ spec: backend: {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} service: - name: {{ $fullName }} + name: {{ .serviceName }} port: number: {{ $svcPort }} {{- else }} - serviceName: {{ $fullName }} + serviceName: {{ .serviceName }} servicePort: {{ $svcPort }} {{- end }} {{- end }} diff --git a/nyxui/templates/service.yaml b/nyxui/templates/service-front.yaml similarity index 79% rename from nyxui/templates/service.yaml rename to nyxui/templates/service-front.yaml index 60862517ccbf08121aa79a056685be0af95c2916..5bdec4b94120fe572c8423f0401cf2809d45c81a 100644 --- a/nyxui/templates/service.yaml +++ b/nyxui/templates/service-front.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: {{ include "nyxui.name" . }} + name: {{ include "nyxui.name" . }}-front labels: {{- include "nyxui.labels" . | nindent 4 }} spec: @@ -13,3 +13,4 @@ spec: name: http selector: {{- include "nyxui.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: front diff --git a/nyxui/templates/service-larvatagger.yaml b/nyxui/templates/service-larvatagger.yaml new file mode 100644 index 0000000000000000000000000000000000000000..32ac7f4c92105f2d576ecc102576c961e828c9dc --- /dev/null +++ b/nyxui/templates/service-larvatagger.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "nyxui.name" . }}-larvatagger + labels: + {{- include "nyxui.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "nyxui.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: larvatagger diff --git a/nyxui/values.yaml b/nyxui/values.yaml index c7bde4b53aa898e7b498be9c48dd79fee0850467..4eacdc45d699d9c4fc5b3c2c480d2e3b1fa4df87 100644 --- a/nyxui/values.yaml +++ b/nyxui/values.yaml @@ -12,6 +12,33 @@ front: pullPolicy: Always service: targetPort: 8080 + resources: + limits: + cpu: "2" + memory: 4Gi + ephemeral-storage: 1Gi + requests: + cpu: "2" + memory: 4Gi + ephemeral-storage: 1Gi + +larvatagger: + image: + repository: registry-gitlab.pasteur.fr/nyx/nyxui.jl + name: larvatagger + tag: latest + pullPolicy: Always + service: + targetPort: 9286 + resources: + limits: + cpu: "2" + memory: 4Gi + ephemeral-storage: 4Gi + requests: + cpu: "2" + memory: 4Gi + ephemeral-storage: 4Gi imagePullSecrets: - name: registry-gitlab @@ -60,21 +87,12 @@ ingress: paths: - path: / pathType: Prefix + serviceName: nyxui-front tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local -resources: - limits: - cpu: "2" - memory: 4Gi - ephemeral-storage: 1Gi - requests: - cpu: "2" - memory: 4Gi - ephemeral-storage: 1Gi - autoscaling: enabled: false minReplicas: 1 @@ -82,18 +100,11 @@ autoscaling: targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80 -# Additional volumes on the output Deployment definition. +# Additional shared volumes on the output Deployment definitions. volumes: [] -# - name: foo -# secret: -# secretName: mysecret -# optional: false -# Additional volumeMounts on the output Deployment definition. +# Additional shared volumeMounts on the output Deployment definitions. volumeMounts: [] -# - name: foo -# mountPath: "/etc/foo" -# readOnly: true nodeSelector: {} diff --git a/src/GenieExtras.jl b/src/GenieExtras.jl index 40cf48a4fa308ea6ab9a3b9c735bfdc133852c19..ebe416c469fe35307a2cbe5faa8386b83008bf6e 100644 --- a/src/GenieExtras.jl +++ b/src/GenieExtras.jl @@ -1,8 +1,11 @@ module GenieExtras import Genie.Renderer.Html +import GenieSession: GenieSession, Session +using NyxWidgets.Base: Cache -export publish_css, appinfo, add_footer +export publish_css, appinfo, add_footer, Session, SessionRegistry, getsessionid, getsession, + clearexpired const project_root = dirname(Base.current_project()) @@ -49,4 +52,129 @@ add_footer(ui::AbstractString, footer=footer) = "$ui$(footer())" add_footer(ui::Function, footer=footer) = () -> add_footer(ui(), footer) +struct SessionRegistry + register + idlength + purgesession + purgesession_args +end + +function SessionRegistry(f, args=(:session_id,); idlength=32) + SessionRegistry(Cache{String, Dict{Symbol, Any}}(), idlength, f, args) +end + +Base.lock(f::Function, registry::SessionRegistry) = lock(f, registry.register) + +function check_session_id_length(registry, session_id) + if !isnothing(registry.idlength) && length(session_id) < registry.idlength + throw("wrong session_id length") + end +end + +function Base.haskey(registry::SessionRegistry, session_id::AbstractString) + lock(registry) do + for session_long_id in keys(registry.register.cache) + if startswith(session_long_id, session_id) + return true + end + end + return false + end +end + +function Base.getindex(registry::SessionRegistry, session_id::AbstractString) + check_session_id_length(registry, session_id) + lock(registry) do + for (session_long_id, records) in pairs(registry.register.cache) + if startswith(session_long_id, session_id) + records[:lastseen] = time() + return records + end + end + throw(KeyError(session_id)) + end +end + +Base.getindex(registry::SessionRegistry, session_id::AbstractString, record::Symbol + ) = registry[session_id][record] + +function getsessionid(session_long_id::String, idlength::Union{Nothing, <:Integer}) + session_id = session_long_id + if !isnothing(idlength) + session_id = string(session_id[1:idlength]) + end + return session_id +end + +function getsessionid(registry::SessionRegistry) + session = GenieSession.session() + session_long_id = session.id + session_id = getsessionid(session_long_id, registry.idlength) + # create the entry in the register if missing + records = lock(registry) do + register = registry.register.cache + if session_id != session_long_id && session_id in keys(register) + # if the session has been registered with its short id (and `getsession`), + # update the short id with the long one + register[session_long_id] = pop!(register, session_id) + else + # registry.register is a NyxWidgets.Cache and `getindex` behaves like `get!` + registry.register[session_long_id] + end + end + # register minimum information + records[:session] = session + records[:lastseen] = time() + # run maintenance routine + clearexpired(registry) + return session_id +end + +function getsession(registry::SessionRegistry, session_id::AbstractString) + if haskey(registry, session_id) # check for long id + registry[session_id] + else # call get! on short id (if session_id is short); not ideal + registry.register[session_id] + end +end + +function clearexpired(registry, expiry::Real=604800) + lock(registry) do + register = registry.register.cache + for (session_long_id, records) in pairs(register) + if !haskey(records, :lastseen) + @warn "Missing key: lastseen" + continue + end + expiry <= time() - records[:lastseen] || continue + # prepare to clear the session; collect the arguments to purgesession + session_id = getsessionid(session_long_id, registry.idlength) + available_args = Dict(:session_id=>session_id, + :session_long_id=>session_long_id, + records...) + @info "Purging session" session_id + pop!(register, session_long_id) + if haskey(records, :session) + session = records[:session] + # see learn.genieframework.com/framework/genie.jl/recipes/session + empty!(session.data) + else + @warn "Missing key: session" + end + # + function get′(arg) + get(available_args, arg) do + @warn "Missing argument for purgesession" arg + nothing + end + end + try + registry.purgesession(get′.(registry.purgesession_args)...) + catch + @error "\`purgesession\` callback failed" + end + end + end +end + end diff --git a/src/apps/catalog/app.jl b/src/apps/catalog/app.jl index cc5c45f9791c9adea27df3892548c63051ec4e4e..4ae5596fcacbd34cff5b7b5d93fc792d66f50ef1 100644 --- a/src/apps/catalog/app.jl +++ b/src/apps/catalog/app.jl @@ -36,9 +36,7 @@ function app_catalog_view() ]))), item(item(class=app, Html.a(href=Router.link_to(:get_larvatagger), [ Html.h1("LarvaTagger", style=header2), - imageview(src="/images/LarvaTagger.png", style=img, - Html.div(class=caption, "Partially available"), - ), + imageview(src="/images/LarvaTagger.png", style=img), ]))), ]), ]) diff --git a/src/apps/larvatagger/app.jl b/src/apps/larvatagger/app.jl index dbdea6201e1c0fe84e2a892f9758f348ceaa7d84..7b3081623789d4afc10123143615d6dcce0ebebe 100644 --- a/src/apps/larvatagger/app.jl +++ b/src/apps/larvatagger/app.jl @@ -3,7 +3,7 @@ module LarvaTagger using NyxUI, NyxUI.Storage, NyxUI.GenieExtras using NyxWidgets.Base: Cache import LarvaTagger as LT -using GenieSession, Stipple +using Stipple import Stipple: @app, @init, @private, @in, @onchange, @onbutton, @click import StippleUI: tooltip @@ -16,21 +16,33 @@ mutable struct Model sizefactor app # TODO: check whether explicitly closing apps helps appdata + kwargs end -const bonito_models = Cache{String, Model}() +function purgesession(model, session_id) + if isnothing(model) + @warn "Session data prematurely lost" + elseif !isnothing(model.app) + close(model.app) + end + purge_appdata(session_id, "larvatagger") + BonitoServer.addsession(bonito_app, session_id; restart=true) +end + +const session_registry = SessionRegistry(purgesession, (:model, :session_id)) const bonito_app = NamedApp("larvatagger", function (session) bucket = getbucket(session, "larvatagger", :read) mkpath(bucket) - model = lock(bonito_models) do - if haskey(bonito_models, session) - bonito_models.cache[session] - else - inputfile = Ref{Union{Nothing, String}}(nothing) - bonito_models.cache[session] = Model(1.0, nothing, inputfile) + model = get!(getsession(session_registry, session), :model) do + kwargs = Dict{Symbol, Any}() + if !isempty(get(ENV, "LARVATAGGER_BACKEND", "")) + kwargs[:backend_directory] = backend = ENV["LARVATAGGER_BACKEND"] + @info "Using environment variable" LARVATAGGER_BACKEND=backend end + inputfile = Ref{Union{Nothing, String}}(nothing) + Model(1.0, nothing, inputfile, kwargs) end exportdir = joinpath("public", session, "larvatagger") function prepare_download(srcfile) @@ -54,18 +66,15 @@ const bonito_app = NamedApp("larvatagger", prepare_download=prepare_download, enable_new_directories=true, enable_delete=true, - viewfactor=model.sizefactor) + viewfactor=model.sizefactor, + model.kwargs...) return app end ) -function purgesession(session) - model = lock(bonito_models) do - pop!(bonito_models.cache, session) - end - isnothing(model.app) || close(model.app) - purge_appdata(session, "larvatagger") - BonitoServer.addsession(bonito_app, session; restart=true) +function purgesession(session_id) + model = pop!(session_registry[session_id], :model, nothing) + purgesession(model, session_id) end @@ -75,10 +84,10 @@ end @in reset_bonito_session = false @onchange isready begin - genie_session = GenieSession.session() - bonito_session_id = genie_session.id[1:32] - if haskey(bonito_models, bonito_session_id) - sizefactor = sizefactors_str[bonito_models[bonito_session_id].sizefactor] + bonito_session_id = getsessionid(session_registry) + if haskey(session_registry[bonito_session_id], :model) + model = session_registry[bonito_session_id, :model] + sizefactor = sizefactors_str[model.sizefactor] else BonitoServer.addsession(bonito_app, bonito_session_id) end @@ -96,9 +105,10 @@ end @onchange sizefactor begin new_sizefactor = sizefactors[sizefactor] - if new_sizefactor != bonito_models[bonito_session_id].sizefactor + model = session_registry[bonito_session_id, :model] + if new_sizefactor != model.sizefactor @info "New size factor; refreshing the iframe" - bonito_models[bonito_session_id].sizefactor = new_sizefactor + model.sizefactor = new_sizefactor BonitoServer.addsession(bonito_app, bonito_session_id; restart=true) # restart width = appwidth[sizefactor] height = appheight[sizefactor] @@ -112,7 +122,11 @@ end end @onbutton reset_bonito_session begin - purgesession(bonito_session_id) + try + purgesession(bonito_session_id) + catch + @error "Error while resetting session" + end # reset UI to defaults bonito_session_id[!] = "" sizefactor[!] = "1.0" diff --git a/src/apps/muscles/Backbone.jl b/src/apps/muscles/Backbone.jl index 5547f559f2007fab4c3a50d8d513536747340842..320d21489b037d1d5de6778dec93bed2a08ede2a 100644 --- a/src/apps/muscles/Backbone.jl +++ b/src/apps/muscles/Backbone.jl @@ -3,6 +3,7 @@ module Backbone using NyxWidgets.Base: Cache using NyxUI.MuscleActivities using NyxUI.Storage +using NyxUI.GenieExtras using Bonito include("MuscleWidgets.jl") @@ -11,58 +12,37 @@ using .MuscleWidgets export hasmodel, getmodel, setmodel, newsequence, getsequence, withsequences, exportsequence, loadsequence, deletesequence, purgesession -# mutable struct Backbone{W} -# widget::Union{Nothing, W} -# channel::Observable{Bonito.JSCode} -# end -# -# Backbone{W}() where {W} = Backbone{W}(nothing) -# -# Backbone{W}(widget::W) where {W} = Backbone{W}(widget, Observable(js"")) -# -# Backbone(widget::W) where {W} = Backbone{W}(widget) -# -# function Bonito.jsrender(session::Session, widget::Backbone) -# isnothing(widget.widget) && error("backbone widget not initialized") -# on(session, widget.channel) do jscode -# evaljs(session, jscode) -# end -# Bonito.jsrender(session, widget.widget) -# end - ## models -const __backbone_cache__ = Cache{String, MuscleWidget}() -const __valid_sessions__ = Dict{String, Bool}() +function purgesession end + +const session_registry = SessionRegistry(purgesession, (:session_id, )) function app(persistent=""; title="Nyx muscle activity") App(; title=title) do session - # # embedded apps are always renderded twice; save time # EDIT: except on Ctrl+R - # valid = get(__valid_sessions__, persistent, false) - # __valid_sessions__[persistent] = !valid - # valid || return @info "New session" session.id cache_id = isempty(persistent) ? session.id : persistent - model = __backbone_cache__[cache_id] + model = session_registry[cache_id, :model] Bonito.jsrender(session, model) end end ## muscle model -getmodel(session_id) = __backbone_cache__[session_id]#.widget +getmodel(session_id) = session_registry[session_id, :model] -# for debugging -getmodel() = first(values(__backbone_cache__))#.widget - -hasmodel(session_id) = haskey(__backbone_cache__, session_id) +hasmodel(session_id) = haskey(session_registry[session_id], :model) function setmodel(session_id, sequence) - __backbone_cache__[session_id] = MuscleWidget(sequence) + records = getsession(session_registry, session_id) + records[:model] = model = MuscleWidget(sequence) + # init :sequences + get!(records, :sequences) do + Cache{Int, MuscleActivity}() + end + return model end -# getchannel(session_id) = __backbone_cache__[session_id].channel - ## sequence model function newsequencename(stem, existing) @@ -97,14 +77,13 @@ function newsequence(session_id, sequence_name, sequence_names, start_time, time return sequence end -const __sequences__ = Cache{String, Cache{Int, MuscleActivity}}() - function getsequence(session_id, sequence_name) model = getmodel(session_id) sequence = nothing if model.sequence[].program_name != sequence_name - lock(__sequences__[session_id]) do - for outer sequence in values(__sequences__[session_id]) + sequences = session_registry[session_id, :sequences] + lock(sequences) do + for outer sequence in values(sequences) sequence.program_name == sequence_name && break end end @@ -116,16 +95,16 @@ end getsequence(session_id) = getmodel(session_id).sequence[] function addsequence(session_id, sequence) - lock(__sequences__[session_id]) do - sequences = __sequences__[session_id] + sequences = session_registry[session_id, :sequences] + lock(sequences) do i = isempty(sequences) ? 0 : maximum(keys(sequences)) sequences[i+1] = sequence end end function withsequences(f, session_id) - lock(__sequences__[session_id]) do - sequences = __sequences__[session_id] + sequences = session_registry[session_id, :sequences] + lock(sequences) do return f(sequences) end end @@ -153,7 +132,7 @@ end function deletesequence(session_id) model = getmodel(session_id) current = model.sequence[].program_name - sequences = __sequences__[session_id] + sequences = session_registry[session_id, :sequences] lock(sequences) do for (ix, seq) in pairs(sequences) if seq.program_name == current @@ -167,19 +146,7 @@ function deletesequence(session_id) end function purgesession(session_id; appname="muscles") - model = lock(__backbone_cache__) do - if session_id in keys(__backbone_cache__.cache) - #pop!(__valid_sessions__, session_id) # not sure what to do with it - pop!(__backbone_cache__.cache, session_id) - end - end - lock(__sequences__) do - if session_id in keys(__sequences__.cache) - pop!(__sequences__.cache, session_id) - end - end - purge_appdata(session_id, appname) - return model + purge_appdata(session_id, appname) end end diff --git a/src/apps/muscles/app.jl b/src/apps/muscles/app.jl index 6140bd2cb844c63fc6efdb74953b6a4ca7958b12..044e4cccdfc0cdf4fe2c0c067892be1daf998909 100644 --- a/src/apps/muscles/app.jl +++ b/src/apps/muscles/app.jl @@ -2,7 +2,7 @@ module MuscleApp using NyxUI, NyxUI.Storage, NyxUI.GenieExtras using Observables -using Genie, GenieSession, Stipple, StippleUI +using Genie, Stipple, StippleUI import Stipple: @app, @init, @private, @in, @out, @onchange, @onbutton, @notify include("Backbone.jl") @@ -20,6 +20,8 @@ const maxlength = getconfig("muscle-activity", "maxlength") const bonito_app = NamedApp(:inherit, Backbone.app) +Backbone.purgesession(session_id) = purgesession(session_id; appname=bonito_app.name) + @app begin @private bonito_session_id = "" @@ -95,7 +97,7 @@ const bonito_app = NamedApp(:inherit, Backbone.app) end @onbutton reset_bonito_session begin - model = purgesession(bonito_session_id; appname=bonito_app.name) + purgesession(bonito_session_id) # reset UI to defaults #bonito_session_id[!] = "" sequence[!] = MuscleActivity("") @@ -445,8 +447,7 @@ function init_model(muscle_model=nothing) muscle_model = @init #@show muscle_model end - genie_session = GenieSession.session() - session_id = genie_session.id[1:32] + session_id = getsessionid(Backbone.session_registry) if hasmodel(session_id) withsequences(session_id) do sequences ids = sort!(collect(keys(sequences))) diff --git a/values-yaml.gotmpl b/values-yaml.gotmpl index d2b4df2f2498b992c4b4f9c3589308ffe201af6f..712200bbbec3e20b4f3fb06e2134726d7fd01cb4 100644 --- a/values-yaml.gotmpl +++ b/values-yaml.gotmpl @@ -7,11 +7,38 @@ replicaCount: 1 front: image: repository: {{ requiredEnv "CI_REGISTRY_IMAGE" }} - name: {{ requiredEnv "IMAGE_NAME" }} + name: {{ env "IMAGE_NAME" | default "front" }} tag: {{ requiredEnv "CI_COMMIT_SHORT_SHA" }} - pullPolicy: {{ requiredEnv "IMAGE_POLICY" }} + pullPolicy: {{ env "IMAGE_POLICY" | default "Always" }} service: - targetPort: {{ requiredEnv "SERVICE_TARGET_PORT" }} + targetPort: {{ env "SERVICE_TARGET_PORT" | default "8080" }} + resources: + limits: + cpu: {{ env "LIMITS_CPU" | default "2" }} + memory: {{ env "LIMITS_MEMORY" | default "4Gi" }} + ephemeral-storage: {{ env "LIMITS_STORAGE" | default "1Gi" }} + requests: + cpu: {{ env "LIMITS_CPU" | default "2" }} + memory: {{ env "LIMITS_MEMORY" | default "4Gi" }} + ephemeral-storage: {{ env "LIMITS_STORAGE" | default "1Gi" }} + +larvatagger: + image: + repository: {{ requiredEnv "CI_REGISTRY_IMAGE" }} + name: {{ env "LT_IMAGE_NAME" | default "larvatagger" }} + tag: {{ env "LT_IMAGE_TAG" | default "latest" }} + pullPolicy: {{ env "LT_IMAGE_POLICY" | default "Always" }} + service: + targetPort: {{ env "LARVATAGGER_PORT" | default "9286" }} + resources: + limits: + cpu: {{ env "LT_LIMITS_CPU" | default "2" }} + memory: {{ env "LT_LIMITS_MEMORY" | default "4Gi" }} + ephemeral-storage: {{ env "LT_LIMITS_STORAGE" | default "4Gi" }} + requests: + cpu: {{ env "LT_LIMITS_CPU" | default "2" }} + memory: {{ env "LT_LIMITS_MEMORY" | default "4Gi" }} + ephemeral-storage: {{ env "LT_LIMITS_STORAGE" | default "4Gi" }} imagePullSecrets: - name: {{ requiredEnv "IMAGE_SECRETS" }} @@ -45,14 +72,14 @@ securityContext: {} service: type: ClusterIP - port: {{ requiredEnv "SERVICE_PORT" }} + port: {{ env "SERVICE_PORT" | default "80" }} ingress: enabled: true name: nyxui - className: {{ requiredEnv "INGRESS_CLASS" }} + className: {{ env "INGRESS_CLASS" | default "internal" }} annotations: - meta.helm.sh/release-name: {{ requiredEnv "INGRESS_CLASS" }} + meta.helm.sh/release-name: nyxui meta.helm.sh/release-namespace: {{ requiredEnv "KUBE_NAMESPACE" }} nginx.ingress.kubernetes.io/proxy-body-size: "0" hosts: @@ -60,21 +87,12 @@ ingress: paths: - path: / pathType: Prefix + serviceName: nyxui-front tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local -resources: - limits: - cpu: {{ requiredEnv "LIMITS_CPU" }} - memory: {{ requiredEnv "LIMITS_MEMORY" }} - ephemeral-storage: {{ requiredEnv "LIMITS_STORAGE" }} - requests: - cpu: {{ requiredEnv "LIMITS_CPU" }} - memory: {{ requiredEnv "LIMITS_MEMORY" }} - ephemeral-storage: {{ requiredEnv "LIMITS_STORAGE" }} - autoscaling: enabled: false minReplicas: 1 @@ -82,18 +100,11 @@ autoscaling: targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80 -# Additional volumes on the output Deployment definition. +# Additional shared volumes on the output Deployment definitions. volumes: [] -# - name: foo -# secret: -# secretName: mysecret -# optional: false -# Additional volumeMounts on the output Deployment definition. +# Additional shared volumeMounts on the output Deployment definitions. volumeMounts: [] -# - name: foo -# mountPath: "/etc/foo" -# readOnly: true nodeSelector: {}