From f82ffd66618ebccddbf1d890f8567935c157c998 Mon Sep 17 00:00:00 2001 From: sonicaj Date: Wed, 14 Feb 2024 13:11:49 +0000 Subject: [PATCH] Publish new changes in catalog --- charts/photoprism/1.1.2/Chart.lock | 6 - charts/photoprism/1.1.2/README.md | 3 - charts/photoprism/1.1.2/app-readme.md | 3 - .../1.1.2/charts/common-2304.0.1.tgz | Bin 4994 -> 0 bytes charts/photoprism/1.1.2/ci/test-values.yaml | 21 - charts/photoprism/1.1.2/ix_values.yaml | 4 - charts/photoprism/1.1.2/metadata.yaml | 36 -- charts/photoprism/1.1.2/questions.yaml | 315 ---------- .../1.1.2/templates/deployment.yaml | 93 --- .../1.1.2/templates/pre-install-job.yaml | 34 - charts/photoprism/1.1.2/templates/secret.yaml | 8 - .../photoprism/1.1.2/templates/service.yaml | 9 - .../templates/tests/deployment-check.yaml | 21 - .../photoprism/{1.1.2 => 2.0.0}/.helmignore | 0 charts/photoprism/2.0.0/Chart.lock | 6 + charts/photoprism/{1.1.2 => 2.0.0}/Chart.yaml | 6 +- charts/photoprism/2.0.0/README.md | 3 + charts/photoprism/2.0.0/app-readme.md | 3 + .../photoprism/2.0.0/charts/common-1.2.9.tgz | Bin 0 -> 63212 bytes charts/photoprism/2.0.0/ci/basic-values.yaml | 17 + charts/photoprism/2.0.0/ci/pass-values.yaml | 13 + charts/photoprism/2.0.0/ix_values.yaml | 43 ++ charts/photoprism/2.0.0/metadata.yaml | 20 + charts/photoprism/2.0.0/migrations/migrate | 98 +++ charts/photoprism/2.0.0/questions.yaml | 593 ++++++++++++++++++ charts/photoprism/2.0.0/templates/NOTES.txt | 1 + .../photoprism/2.0.0/templates/_migration.tpl | 35 ++ .../2.0.0/templates/_persistance.tpl | 40 ++ .../2.0.0/templates/_photoprism.tpl | 74 +++ charts/photoprism/2.0.0/templates/_portal.tpl | 12 + .../photoprism/2.0.0/templates/_service.tpl | 15 + charts/photoprism/2.0.0/templates/common.yaml | 13 + 32 files changed, 989 insertions(+), 556 deletions(-) delete mode 100644 charts/photoprism/1.1.2/Chart.lock delete mode 100644 charts/photoprism/1.1.2/README.md delete mode 100644 charts/photoprism/1.1.2/app-readme.md delete mode 100644 charts/photoprism/1.1.2/charts/common-2304.0.1.tgz delete mode 100644 charts/photoprism/1.1.2/ci/test-values.yaml delete mode 100644 charts/photoprism/1.1.2/ix_values.yaml delete mode 100644 charts/photoprism/1.1.2/metadata.yaml delete mode 100644 charts/photoprism/1.1.2/questions.yaml delete mode 100644 charts/photoprism/1.1.2/templates/deployment.yaml delete mode 100644 charts/photoprism/1.1.2/templates/pre-install-job.yaml delete mode 100644 charts/photoprism/1.1.2/templates/secret.yaml delete mode 100644 charts/photoprism/1.1.2/templates/service.yaml delete mode 100644 charts/photoprism/1.1.2/templates/tests/deployment-check.yaml rename charts/photoprism/{1.1.2 => 2.0.0}/.helmignore (100%) create mode 100644 charts/photoprism/2.0.0/Chart.lock rename charts/photoprism/{1.1.2 => 2.0.0}/Chart.yaml (86%) create mode 100644 charts/photoprism/2.0.0/README.md create mode 100644 charts/photoprism/2.0.0/app-readme.md create mode 100644 charts/photoprism/2.0.0/charts/common-1.2.9.tgz create mode 100644 charts/photoprism/2.0.0/ci/basic-values.yaml create mode 100644 charts/photoprism/2.0.0/ci/pass-values.yaml create mode 100644 charts/photoprism/2.0.0/ix_values.yaml create mode 100644 charts/photoprism/2.0.0/metadata.yaml create mode 100755 charts/photoprism/2.0.0/migrations/migrate create mode 100644 charts/photoprism/2.0.0/questions.yaml create mode 100644 charts/photoprism/2.0.0/templates/NOTES.txt create mode 100644 charts/photoprism/2.0.0/templates/_migration.tpl create mode 100644 charts/photoprism/2.0.0/templates/_persistance.tpl create mode 100644 charts/photoprism/2.0.0/templates/_photoprism.tpl create mode 100644 charts/photoprism/2.0.0/templates/_portal.tpl create mode 100644 charts/photoprism/2.0.0/templates/_service.tpl create mode 100644 charts/photoprism/2.0.0/templates/common.yaml diff --git a/charts/photoprism/1.1.2/Chart.lock b/charts/photoprism/1.1.2/Chart.lock deleted file mode 100644 index 436bb99b1e..0000000000 --- a/charts/photoprism/1.1.2/Chart.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: common - repository: file://../../../common/2304.0.1 - version: 2304.0.1 -digest: sha256:1ed155c6760e1166e2cb75b52bc5e81c6bdf0252c16ff5ede001157077c41670 -generated: "2023-04-24T13:40:53.604174144+03:00" diff --git a/charts/photoprism/1.1.2/README.md b/charts/photoprism/1.1.2/README.md deleted file mode 100644 index ed190c02d6..0000000000 --- a/charts/photoprism/1.1.2/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Photo Prism - -PhotoPrism is a server-based application for browsing, organizing and sharing your personal photo collection. diff --git a/charts/photoprism/1.1.2/app-readme.md b/charts/photoprism/1.1.2/app-readme.md deleted file mode 100644 index ed190c02d6..0000000000 --- a/charts/photoprism/1.1.2/app-readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# Photo Prism - -PhotoPrism is a server-based application for browsing, organizing and sharing your personal photo collection. diff --git a/charts/photoprism/1.1.2/charts/common-2304.0.1.tgz b/charts/photoprism/1.1.2/charts/common-2304.0.1.tgz deleted file mode 100644 index a8e95b4c04fe6850a10eacca635d4fa7c8420929..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4994 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 M|5xQq832j^0Nc+1KL7v# diff --git a/charts/photoprism/1.1.2/ci/test-values.yaml b/charts/photoprism/1.1.2/ci/test-values.yaml deleted file mode 100644 index ba31c4d883..0000000000 --- a/charts/photoprism/1.1.2/ci/test-values.yaml +++ /dev/null @@ -1,21 +0,0 @@ -appVolumeMounts: - import: - emptyDir: true - mountPath: /photoprism/import - original: - emptyDir: true - mountPath: /photoprism/originals - storage: - emptyDir: true - mountPath: /photoprism/storage -dnsConfig: - options: [] -emptyDirVolumes: true -environmentVariables: [] -extraAppVolumeMounts: [] -ownerGID: 568 -ownerUID: 568 -password: admin123 -public: false -web_port: 32000 -global: {} diff --git a/charts/photoprism/1.1.2/ix_values.yaml b/charts/photoprism/1.1.2/ix_values.yaml deleted file mode 100644 index d81ef841d7..0000000000 --- a/charts/photoprism/1.1.2/ix_values.yaml +++ /dev/null @@ -1,4 +0,0 @@ -image: - pullPolicy: IfNotPresent - repository: photoprism/photoprism - tag: '231128' diff --git a/charts/photoprism/1.1.2/metadata.yaml b/charts/photoprism/1.1.2/metadata.yaml deleted file mode 100644 index 0208f67bda..0000000000 --- a/charts/photoprism/1.1.2/metadata.yaml +++ /dev/null @@ -1,36 +0,0 @@ -runAsContext: - - userName: root - groupName: root - gid: 0 - uid: 0 - description: Photoprism runs as root user. -capabilities: - - name: CHOWN - description: Photoprism is able to chown files. - - name: FOWNER - description: Photoprism is able to bypass permission checks for it's sub-processes. - - name: SYS_CHROOT - description: Photoprism is able to use chroot. - - name: MKNOD - description: Photoprism is able to create device nodes. - - name: DAC_OVERRIDE - description: Photoprism is able to bypass permission checks. - - name: FSETID - description: Photoprism is able to set file capabilities. - - name: KILL - description: Photoprism is able to kill processes. - - name: SETGID - description: Photoprism is able to set group ID for it's sub-processes. - - name: SETUID - description: Photoprism is able to set user ID for it's sub-processes. - - name: SETPCAP - description: Photoprism is able to set process capabilities. - - name: NET_BIND_SERVICE - description: Photoprism is able to bind to privileged ports. - - name: SETFCAP - description: Photoprism is able to set file capabilities. - - name: NET_RAW - description: Photoprism is able to use raw sockets. - - name: AUDIT_WRITE - description: Photoprism is able to write to audit log. -hostMounts: [] diff --git a/charts/photoprism/1.1.2/questions.yaml b/charts/photoprism/1.1.2/questions.yaml deleted file mode 100644 index 9eea1d8be6..0000000000 --- a/charts/photoprism/1.1.2/questions.yaml +++ /dev/null @@ -1,315 +0,0 @@ -groups: - - name: "Configuration" - description: "Photo Prism application configuration" - - name: "Storage" - description: "Configure storage for photo prism" - - name: "Networking" - description: "Networking Configuration for photo prism" - - name: "Advanced DNS Settings" - description: "Configure DNS settings" - - name: "Resource Reservation" - description: "Specify resources to be allocated to workload" - - name: "Resource Limits" - description: "Set CPU/memory limits for Kubernetes Pod" - -portals: - web_portal: - protocols: - - "http" - host: - - "$node_ip" - ports: - - "$variable-web_port" - path: "/" - -questions: - - variable: host_network - group: Networking - label: Host Network - description: | - Bind to the host network. It's recommended to keep this disabled but may be needed for photoprism to be reachable from a hostNetworked VPN.
- schema: - type: boolean - default: false - - - variable: web_port - label: "Web Port for photo prism" - group: Networking - schema: - type: int - min: 8000 - max: 65535 - default: 20800 - required: true - - - variable: dnsConfig - label: "DNS Configuration" - group: "Advanced DNS Settings" - schema: - type: dict - attrs: - - variable: options - label: "DNS Options" - schema: - type: list - items: - - variable: optionsEntry - label: "Option Entry Configuration" - schema: - type: dict - attrs: - - variable: name - label: "Option Name" - schema: - type: string - required: true - - variable: value - label: "Option Value" - schema: - type: string - required: true - - - variable: ownerUID - label: "Storage User ID" - description: "User ID of the storage volume being used (application will chown the storage volume path with specified UID)" - group: Configuration - schema: - type: int - default: 568 - min: 1 - max: 65535 - - - variable: ownerGID - label: "Storage Group ID" - description: "Group ID of the storage volume being used (application will chown the storage volume path with specified GID)" - group: Configuration - schema: - type: int - default: 568 - min: 1 - max: 65535 - - - variable: password - label: "Password" - group: "Configuration" - schema: - type: string - private: true - required: true - empty: false - immutable: true - default: "admin123" - show_if: [["public", "=", false]] - - - variable: public - label: "Enable Public Access" - description: "Disable password authentication, WebDAV, and the advanced settings page" - group: "Configuration" - schema: - type: boolean - default: false - - - variable: environmentVariables - label: "Photo Prism environment" - group: "Configuration" - schema: - type: list - default: [] - items: - - variable: environmentVariable - label: "Environment Variable" - schema: - type: dict - attrs: - - variable: name - label: "Name" - schema: - type: string - - variable: value - label: "Value" - schema: - type: string - - - variable: appVolumeMounts - label: "Photo Prism Storage" - group: "Storage" - schema: - type: dict - attrs: - - variable: original - label: "Storage Volume for Original Media" - schema: - type: dict - attrs: - - variable: datasetName - label: "Original Storage Volume Dataset Name" - schema: - type: string - hidden: true - $ref: - - "normalize/ixVolume" - show_if: [["hostPathEnabled", "=", false]] - default: "ix-photoprism_original" - editable: false - - variable: mountPath - label: "Original Storage Mount Path" - description: "Path where the volume will be mounted inside the pod" - schema: - type: path - hidden: true - editable: true - default: "/photoprism/originals" - - variable: readOnly - label: "Read Only" - description: "Mount volume as read only" - schema: - type: boolean - default: false - - variable: hostPathEnabled - label: "Enable Custom Host Path for Photo Prism Original Storage Volume" - schema: - type: boolean - default: false - show_subquestions_if: true - subquestions: - - variable: hostPath - label: "Host Path for Photo Prism Original Storage Volume" - schema: - type: hostpath - required: true - - variable: storage - label: "Storage Volume for sidecar/cache/database" - schema: - type: dict - attrs: - - variable: datasetName - label: "Storage Volume Dataset Name" - schema: - type: string - hidden: true - $ref: - - "normalize/ixVolume" - show_if: [["hostPathEnabled", "=", false]] - default: "ix-photoprism_storage" - editable: false - - variable: mountPath - label: "Storage Mount Path" - description: "Path where the volume will be mounted inside the pod" - schema: - type: path - hidden: true - editable: true - default: "/photoprism/storage" - - variable: hostPathEnabled - label: "Enable Custom Host Path for Photo Prism Storage Volume" - schema: - type: boolean - default: false - show_subquestions_if: true - subquestions: - - variable: hostPath - label: "Host Path for Photo Prism Storage Volume" - schema: - type: hostpath - required: true - - variable: import - label: "Storage Volume for imports" - schema: - type: dict - attrs: - - variable: datasetName - label: "Import Storage Volume Dataset Name" - schema: - type: string - hidden: true - $ref: - - "normalize/ixVolume" - show_if: [["hostPathEnabled", "=", false]] - default: "ix-photoprism_import" - editable: false - - variable: mountPath - label: "Storage Mount Path" - description: "Path where the volume will be mounted inside the pod" - schema: - type: path - hidden: true - editable: true - default: "/photoprism/import" - - variable: hostPathEnabled - label: "Enable Custom Host Path for Photo Prism Import Storage Volume" - schema: - type: boolean - default: false - show_subquestions_if: true - subquestions: - - variable: hostPath - label: "Host Path for Photo Prism Import Storage Volume" - schema: - type: hostpath - required: true - - - variable: extraAppVolumeMounts - label: "Extra Host Path Volumes" - group: "Storage" - schema: - type: list - items: - - variable: extraAppVolume - label: "Host Path Volume" - description: "Add an extra host path volume for Photo Prism application" - schema: - type: dict - attrs: - - variable: mountPath - label: "Mount Path in Pod" - description: "Path where the volume will be mounted inside the pod" - schema: - type: path - required: true - - variable: readOnly - label: "Read Only" - description: "Mount volume as read only" - schema: - type: boolean - default: false - - variable: hostPath - label: "Host Path" - description: "Host path" - schema: - type: hostpath - required: true - - # Specify GPU configuration - - variable: gpuConfiguration - label: "GPU Configuration" - group: "Resource Reservation" - schema: - type: dict - $ref: - - "definitions/gpuConfiguration" - attrs: [] - - - variable: enableResourceLimits - label: "Enable Pod resource limits" - group: "Resource Limits" - schema: - type: boolean - default: false - - variable: cpuLimit - label: "CPU Limit" - description: "CPU resource limit allow plain integer values with suffix m(milli) e.g 1000m, 100." - group: "Resource Limits" - schema: - type: string - show_if: [["enableResourceLimits", "=", true]] - valid_chars: "^\\d+(?:\\.\\d+(?!.*m$)|m?$)" - default: "4000m" - - variable: memLimit - label: "Memory Limit" - group: "Resource Limits" - description: "Memory limits is specified by number of bytes. Followed by quantity suffix like E,P,T,G,M,k and Ei,Pi,Ti,Mi,Gi,Ki can also be used. e.g 129e6, 129M, 128974848000m, 123Mi" - schema: - type: string - show_if: [["enableResourceLimits", "=", true]] - valid_chars: "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$" - default: "8Gi" diff --git a/charts/photoprism/1.1.2/templates/deployment.yaml b/charts/photoprism/1.1.2/templates/deployment.yaml deleted file mode 100644 index 6d8729db89..0000000000 --- a/charts/photoprism/1.1.2/templates/deployment.yaml +++ /dev/null @@ -1,93 +0,0 @@ -{{ include "common.storage.hostPathValidate" .Values }} -apiVersion: {{ template "common.capabilities.deployment.apiVersion" . }} -kind: Deployment -metadata: - name: {{ template "common.names.fullname" . }} - labels: - app: {{ template "common.names.name" . }} - chart: {{ template "common.names.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - annotations: - rollme: {{ randAlphaNum 5 | quote }} -spec: - replicas: {{ (default 1 .Values.replicas) }} - strategy: - type: "Recreate" - selector: - matchLabels: - app: {{ template "common.names.name" . }} - release: {{ .Release.Name }} - template: - metadata: - name: {{ template "common.names.fullname" . }} - labels: - app: {{ template "common.names.name" . }} - release: {{ .Release.Name }} - {{- include "common.labels.selectorLabels" . | nindent 8 }} - annotations: {{ include "common.annotations" . | nindent 8 }} - spec: - hostNetwork: {{ .Values.host_network }} - {{- if hasKey .Values "global" }} - {{- if hasKey .Values.global "ixChartContext" }} - {{- if .Values.global.ixChartContext.addNvidiaRuntimeClass }} - runtimeClassName: {{ .Values.global.ixChartContext.nvidiaRuntimeClassName }} - {{- end }} - {{- end }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ include "common.resources.limitation" . | nindent 10 }} - {{ include "common.containers.imageConfig" .Values.image | nindent 10 }} - volumeMounts: {{ include "common.storage.configureAppVolumeMountsInContainer" .Values | nindent 12 }} - {{ range $index, $hostPathConfiguration := .Values.extraAppVolumeMounts }} - - name: extrappvolume-{{ $index }} - mountPath: {{ $hostPathConfiguration.mountPath }} - readOnly: {{ $hostPathConfiguration.readOnly | default false }} - {{ end }} - ports: - - name: web - containerPort: {{ .Values.web_port }} - readinessProbe: - httpGet: - path: / - port: {{ .Values.web_port }} - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 5 - successThreshold: 2 - livenessProbe: - httpGet: - path: / - port: {{ .Values.web_port }} - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 5 - successThreshold: 1 - startupProbe: - httpGet: - path: / - port: {{ .Values.web_port }} - initialDelaySeconds: 10 - periodSeconds: 5 - timeoutSeconds: 2 - failureThreshold: 60 - successThreshold: 1 - env: - {{ $secretName := (include "common.names.fullname" .) }} - {{ $envList := (default list .Values.environmentVariables) }} - {{ $envList = mustAppend $envList (dict "name" "PHOTOPRISM_HTTP_PORT" "value" .Values.web_port) }} - {{ $envList = mustAppend $envList (dict "name" "PHOTOPRISM_ADMIN_PASSWORD" "valueFromSecret" true "secretName" $secretName "secretKey" "password") }} - {{ if .Values.public }} - {{ $envList = mustAppend $envList (dict "name" "PHOTOPRISM_PUBLIC" "value" "true") }} - {{ end }} - {{ include "common.containers.environmentVariables" (dict "environmentVariables" $envList) | nindent 12 }} -{{ include "common.networking.dnsConfiguration" .Values | nindent 6 }} - volumes: {{ include "common.storage.configureAppVolumes" .Values | nindent 8 }} - {{ range $index, $hostPathConfiguration := .Values.extraAppVolumeMounts }} - - name: extrappvolume-{{ $index }} - hostPath: - path: {{ $hostPathConfiguration.hostPath }} - {{ end }} diff --git a/charts/photoprism/1.1.2/templates/pre-install-job.yaml b/charts/photoprism/1.1.2/templates/pre-install-job.yaml deleted file mode 100644 index 0a7b6b8625..0000000000 --- a/charts/photoprism/1.1.2/templates/pre-install-job.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: "{{ template "common.names.fullname" . }}-preinstall-job" - labels: - app.kubernetes.io/managed-by: {{ .Release.Service | quote }} - app.kubernetes.io/instance: {{ .Release.Name | quote }} - app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} - helm.sh/chart: {{ template "common.names.chart" . }} - annotations: - "helm.sh/hook": pre-install - "helm.sh/hook-delete-policy": hook-succeeded -spec: - template: - metadata: - name: "{{ template "common.names.fullname" . }}-preinstall-hook" - labels: - app.kubernetes.io/managed-by: {{ .Release.Service | quote }} - app.kubernetes.io/instance: {{ .Release.Name | quote }} - helm.sh/chart: {{ template "common.names.chart" . }} - spec: - restartPolicy: Never - containers: - - name: pre-install-job - image: "alpine:latest" - command: - - "chown" - - "-R" - - "{{ .Values.ownerUID }}:{{ .Values.ownerGID }}" - - "{{ .Values.appVolumeMounts.storage.mountPath }}" - - "{{ .Values.appVolumeMounts.original.mountPath }}" - - "{{ .Values.appVolumeMounts.import.mountPath }}" - volumeMounts: {{ include "common.storage.configureAppVolumeMountsInContainer" .Values | nindent 12 }} - volumes: {{ include "common.storage.configureAppVolumes" .Values | nindent 8 }} diff --git a/charts/photoprism/1.1.2/templates/secret.yaml b/charts/photoprism/1.1.2/templates/secret.yaml deleted file mode 100644 index e531b6015e..0000000000 --- a/charts/photoprism/1.1.2/templates/secret.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "common.names.fullname" . }} - labels: {{ include "common.labels" . | nindent 4 }} -type: Opaque -data: - password: {{ .Values.password | b64enc | quote }} diff --git a/charts/photoprism/1.1.2/templates/service.yaml b/charts/photoprism/1.1.2/templates/service.yaml deleted file mode 100644 index bec4be3b99..0000000000 --- a/charts/photoprism/1.1.2/templates/service.yaml +++ /dev/null @@ -1,9 +0,0 @@ -{{ $selectors := list }} -{{ $selectors = mustAppend $selectors (dict "key" "app" "value" (include "common.names.name" .) ) }} -{{ $selectors = mustAppend $selectors (dict "key" "release" "value" .Release.Name ) }} -{{ $ports := list }} -{{ $ports = mustAppend $ports (dict "name" "web" "port" .Values.web_port "nodePort" .Values.web_port "targetPort" .Values.web_port) }} -{{ $params := . }} -{{ $_ := set $params "commonService" (dict "type" "NodePort" "ports" $ports ) }} -{{ $_1 := set .Values "extraSelectorLabels" $selectors }} -{{ include "common.classes.service" $params }} diff --git a/charts/photoprism/1.1.2/templates/tests/deployment-check.yaml b/charts/photoprism/1.1.2/templates/tests/deployment-check.yaml deleted file mode 100644 index da2a65ed8d..0000000000 --- a/charts/photoprism/1.1.2/templates/tests/deployment-check.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- $serviceName := (include "common.names.fullname" .) -}} -apiVersion: v1 -kind: Pod -metadata: - name: {{ .Release.Name }}-photoprism - labels: - app: {{ .Release.Name }} - release: {{ .Release.Name }} - annotations: - "helm.sh/hook": test -spec: - containers: - - name: test-curl - image: alpine/curl - imagePullPolicy: "IfNotPresent" - command: - - /bin/sh - - -ec - - | - curl --connect-timeout 5 --max-time 10 --retry 5 --retry-delay 15 --retry-max-time 90 --retry-all-errors -ksf http://{{ $serviceName }}:{{.Values.web_port}}/ - restartPolicy: Never diff --git a/charts/photoprism/1.1.2/.helmignore b/charts/photoprism/2.0.0/.helmignore similarity index 100% rename from charts/photoprism/1.1.2/.helmignore rename to charts/photoprism/2.0.0/.helmignore diff --git a/charts/photoprism/2.0.0/Chart.lock b/charts/photoprism/2.0.0/Chart.lock new file mode 100644 index 0000000000..9f9ddbdc9d --- /dev/null +++ b/charts/photoprism/2.0.0/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: file://../../../common + version: 1.2.9 +digest: sha256:af1a9a1f87e3e48453c9f25f909f5ebcd7fa6e25162b7b425448ba752bcdbc5c +generated: "2024-02-12T15:40:23.281898434+02:00" diff --git a/charts/photoprism/1.1.2/Chart.yaml b/charts/photoprism/2.0.0/Chart.yaml similarity index 86% rename from charts/photoprism/1.1.2/Chart.yaml rename to charts/photoprism/2.0.0/Chart.yaml index 3f00c0da8e..bd80a78c9f 100644 --- a/charts/photoprism/1.1.2/Chart.yaml +++ b/charts/photoprism/2.0.0/Chart.yaml @@ -3,7 +3,7 @@ description: AI-powered app for browsing, organizing & sharing your photo collec annotations: title: PhotoPrism type: application -version: 1.1.2 +version: 2.0.0 apiVersion: v2 appVersion: '231128' kubeVersion: '>=1.16.0-0' @@ -13,8 +13,8 @@ maintainers: email: dev@ixsystems.com dependencies: - name: common - repository: file://../../../common/2304.0.1 - version: 2304.0.1 + repository: file://../../../common + version: 1.2.9 home: https://photoprism.app/ icon: https://media.sys.truenas.net/apps/photoprism/icons/icon.svg sources: diff --git a/charts/photoprism/2.0.0/README.md b/charts/photoprism/2.0.0/README.md new file mode 100644 index 0000000000..8d87c2a141 --- /dev/null +++ b/charts/photoprism/2.0.0/README.md @@ -0,0 +1,3 @@ +# PhotoPrism + +[PhotoPrism](https://photoprism.app/) is a server-based application for browsing, organizing and sharing your personal photo collection. diff --git a/charts/photoprism/2.0.0/app-readme.md b/charts/photoprism/2.0.0/app-readme.md new file mode 100644 index 0000000000..8d87c2a141 --- /dev/null +++ b/charts/photoprism/2.0.0/app-readme.md @@ -0,0 +1,3 @@ +# PhotoPrism + +[PhotoPrism](https://photoprism.app/) is a server-based application for browsing, organizing and sharing your personal photo collection. diff --git a/charts/photoprism/2.0.0/charts/common-1.2.9.tgz b/charts/photoprism/2.0.0/charts/common-1.2.9.tgz new file mode 100644 index 0000000000000000000000000000000000000000..bfdb5d00a5ee745cfc80d9df706298a0a6dc09e8 GIT binary patch literal 63212 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

M=$ifu2LfweTBd^R7x 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

VeB5xZI02O2Y((|FZd!pMnUA^ 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 ASpWb4 literal 0 HcmV?d00001 diff --git a/charts/photoprism/2.0.0/ci/basic-values.yaml b/charts/photoprism/2.0.0/ci/basic-values.yaml new file mode 100644 index 0000000000..ef99c57e84 --- /dev/null +++ b/charts/photoprism/2.0.0/ci/basic-values.yaml @@ -0,0 +1,17 @@ +photoprismNetwork: + webPort: 30489 + +photoprismConfig: + public: true + +photoprismID: + user: 1000 + group: 1000 + +photoprismStorage: + import: + type: pvc + originals: + type: pvc + storage: + type: pvc diff --git a/charts/photoprism/2.0.0/ci/pass-values.yaml b/charts/photoprism/2.0.0/ci/pass-values.yaml new file mode 100644 index 0000000000..16ae1123af --- /dev/null +++ b/charts/photoprism/2.0.0/ci/pass-values.yaml @@ -0,0 +1,13 @@ +photoprismNetwork: + webPort: 30489 + +photoprismConfig: + password: secret + +photoprismStorage: + import: + type: pvc + originals: + type: pvc + storage: + type: pvc diff --git a/charts/photoprism/2.0.0/ix_values.yaml b/charts/photoprism/2.0.0/ix_values.yaml new file mode 100644 index 0000000000..be4be1e2e4 --- /dev/null +++ b/charts/photoprism/2.0.0/ix_values.yaml @@ -0,0 +1,43 @@ +image: + pullPolicy: IfNotPresent + repository: photoprism/photoprism + tag: '231128' + +resources: + limits: + cpu: 4000m + memory: 8Gi + +podOptions: + dnsConfig: + options: [] + +photoprismConfig: + public: false + password: '' + additionalEnvs: [] + +photoprismNetwork: + webPort: 20800 + hostNetwork: false + +photoprismID: + user: 568 + group: 568 + +photoprismStorage: + import: + type: ixVolume + ixVolumeConfig: + datasetName: import + storage: + type: ixVolume + ixVolumeConfig: + datasetName: storage + originals: + type: ixVolume + ixVolumeConfig: + datasetName: originals + additionalStorages: [] + +photoprismGPU: {} diff --git a/charts/photoprism/2.0.0/metadata.yaml b/charts/photoprism/2.0.0/metadata.yaml new file mode 100644 index 0000000000..624e23c359 --- /dev/null +++ b/charts/photoprism/2.0.0/metadata.yaml @@ -0,0 +1,20 @@ +runAsContext: + - userName: photoprism + groupName: photoprism + gid: 0 + uid: 0 + description: Photoprism run as a root user. +capabilities: + - name: CHOWN + description: Photoprism is able to chown files. + - name: FOWNER + description: Photoprism is able to bypass permission checks for it's sub-processes. + - name: DAC_OVERRIDE + description: Photoprism is able to bypass permission checks. + - name: SETGID + description: Photoprism is able to set group ID for it's sub-processes. + - name: SETUID + description: Photoprism is able to set user ID for it's sub-processes. + - name: KILL + description: Photoprism is able to kill processes. +hostMounts: [] diff --git a/charts/photoprism/2.0.0/migrations/migrate b/charts/photoprism/2.0.0/migrations/migrate new file mode 100755 index 0000000000..7c8b5322b4 --- /dev/null +++ b/charts/photoprism/2.0.0/migrations/migrate @@ -0,0 +1,98 @@ +#!/usr/bin/python3 +import json +import os +import sys + +def migrate_volume(volume): + return { + 'type': 'hostPath', + 'readOnly': volume.get('readOnly', False), + 'hostPathConfig': { + 'hostPath': volume['hostPath'] + }, + } if volume.get('hostPathEnabled', False) else { + 'type': 'ixVolume', + 'readOnly': volume.get('readOnly', False), + 'ixVolumeConfig': { + 'datasetName': volume['datasetName'], + }, + } + +def migrate_common_lib(values): + delete_keys = [ + 'memLimit', 'cpuLimit', 'enableResourceLimits', 'extraAppVolumeMounts', + 'password', 'public', 'ownerUID', 'ownerGID', 'dnsConfig', 'environmentVariables', + 'web_port', 'host_network', 'appVolumeMounts', 'gpuConfiguration' + ] + + values.update({ + # Migrate Network + 'photoprismNetwork': { + 'webPort': values['web_port'], + 'hostNetwork': values['host_network'], + }, + # Migrate Resources + 'resources': { + 'limits': { + 'cpu': values.get('cpuLimit', '4000m'), + 'memory': values.get('memLimit', '8Gi'), + } + }, + 'photoprismGPU': values.get('gpuConfiguration', {}), + # Migrate DNS + 'podOptions': { + 'dnsConfig': { + 'options': [ + {'name': opt['name'], 'value': opt['value']} + for opt in values.get('dnsConfig', {}).get('options', []) + ] + } + }, + # Migrate run context + 'photoprismID': { + 'user': values['ownerUID'], + 'group': values['ownerGID'], + }, + # Migrate Config + 'photoprismConfig': { + 'public': values['public'], + 'password': values.get('password', ''), + 'additionalEnvs': values.get('environmentVariables', []), + }, + # Migrate Storage + 'photoprismStorage': { + 'import': migrate_volume(values['appVolumeMounts']['import']), + 'storage': migrate_volume(values['appVolumeMounts']['storage']), + 'originals': migrate_volume(values['appVolumeMounts']['original']), + 'additionalStorages': [ + { + 'type': 'hostPath', + 'hostPathConfig': {'hostPath': e['hostPath']}, + 'mountPath': e['mountPath'], + 'readOnly': e.get('readOnly', False), + } + for e in values.get('extraAppVolumeMounts', []) + ], + }, + }) + + for k in delete_keys: + values.pop(k, None) + + return values + +def migrate(values): + # If this missing, we have already migrated + if not 'appVolumeMounts' in values.keys(): + return values + + return migrate_common_lib(values) + + +if __name__ == '__main__': + if len(sys.argv) != 2: + exit(1) + + if os.path.exists(sys.argv[1]): + with open(sys.argv[1], 'r') as f: + print(json.dumps(migrate(json.loads(f.read())))) diff --git a/charts/photoprism/2.0.0/questions.yaml b/charts/photoprism/2.0.0/questions.yaml new file mode 100644 index 0000000000..30fcbaa600 --- /dev/null +++ b/charts/photoprism/2.0.0/questions.yaml @@ -0,0 +1,593 @@ +groups: + - name: Photoprism Configuration + description: Configure Photoprism + - name: User and Group Configuration + description: Configure User and Group for Photoprism + - name: Advanced Pod Configuration + description: Configure Advanced Pod Options for Photoprism + - name: Network Configuration + description: Configure Network for Photoprism + - name: Storage Configuration + description: Configure Storage for Photoprism + - name: Resources Configuration + description: Configure Resources for Photoprism + +portals: + web_portal: + protocols: + - "$kubernetes-resource_configmap_portal_protocol" + host: + - "$kubernetes-resource_configmap_portal_host" + ports: + - "$kubernetes-resource_configmap_portal_port" + path: "$kubernetes-resource_configmap_portal_path" + +questions: + - variable: photoprismConfig + label: "" + group: Photoprism Configuration + schema: + type: dict + attrs: + - variable: public + label: Public + description: | + Enable public access to Photoprism.
+ If enabled, Photoprism will be accessible without authentication. + schema: + type: boolean + default: false + - variable: password + label: Password + description: | + Set a password for Photoprism.
+ If public access is enabled, a password is required. + schema: + type: string + default: "" + required: true + show_if: [["public", "=", false]] + private: true + - variable: additionalEnvs + label: Additional Environment Variables + description: Configure additional environment variables for Photoprism. + schema: + type: list + default: [] + items: + - variable: env + label: Environment Variable + schema: + type: dict + attrs: + - variable: name + label: Name + schema: + type: string + required: true + - variable: value + label: Value + schema: + type: string + required: true + + - variable: photoprismID + label: "" + group: User and Group Configuration + schema: + type: dict + attrs: + - variable: user + label: User ID + description: The user id that Photoprism files will be owned by. + schema: + type: int + min: 568 + default: 568 + required: true + - variable: group + label: Group ID + description: The group id that Photoprism files will be owned by. + schema: + type: int + min: 568 + default: 568 + required: true + + - variable: podOptions + label: "" + group: Advanced Pod Configuration + schema: + type: dict + attrs: + - variable: dnsConfig + label: Advanced DNS Configuration + schema: + type: dict + attrs: + - variable: options + label: DNS Options + schema: + type: list + items: + - variable: optionsEntry + label: DNS Option Entry + schema: + type: dict + attrs: + - variable: name + label: Option Name + schema: + type: string + required: true + - variable: value + label: Option Value + schema: + type: string + required: true + + - variable: photoprismNetwork + label: "" + group: Network Configuration + schema: + type: dict + attrs: + - variable: webPort + label: WebUI Port + description: The port for Photoprism WebUI + schema: + type: int + default: 20800 + min: 9000 + max: 65535 + required: true + - variable: hostNetwork + label: Host Network + description: | + Bind to the host network. It's recommended to keep this disabled. + schema: + type: boolean + default: false + + - variable: photoprismStorage + label: "" + group: Storage Configuration + schema: + type: dict + attrs: + - variable: import + label: Photoprism Import Storage + description: The path to store Photoprism Import. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system. + schema: + type: string + required: true + immutable: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - variable: ixVolumeConfig + label: ixVolume Configuration + description: The configuration for the ixVolume dataset. + schema: + type: dict + show_if: [["type", "=", "ixVolume"]] + $ref: + - "normalize/ixVolume" + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + required: true + immutable: true + hidden: true + default: "import" + - variable: aclEntries + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + - variable: hostPathConfig + label: Host Path Configuration + schema: + type: dict + show_if: [["type", "=", "hostPath"]] + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: acl + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + $ref: + - "normalize/acl" + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["aclEnable", "=", false]] + required: true + - variable: storage + label: Photoprism Storage + description: The path to store Photoprism Storage. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system. + schema: + type: string + required: true + immutable: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - variable: ixVolumeConfig + label: ixVolume Configuration + description: The configuration for the ixVolume dataset. + schema: + type: dict + show_if: [["type", "=", "ixVolume"]] + $ref: + - "normalize/ixVolume" + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + required: true + immutable: true + hidden: true + default: "storage" + - variable: aclEntries + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + - variable: hostPathConfig + label: Host Path Configuration + schema: + type: dict + show_if: [["type", "=", "hostPath"]] + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: acl + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + $ref: + - "normalize/acl" + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["aclEnable", "=", false]] + required: true + - variable: originals + label: Photoprism Originals Storage + description: The path to store Photoprism Originals. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system.
+ schema: + type: string + required: true + immutable: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - value: "emptyDir" + description: emptyDir (Temporary directory created on the disk or in memory) + - variable: readOnly + label: Read Only + description: Mount the volume as read only. + schema: + type: boolean + default: false + - variable: ixVolumeConfig + label: ixVolume Configuration + description: The configuration for the ixVolume dataset. + schema: + type: dict + show_if: [["type", "=", "ixVolume"]] + $ref: + - "normalize/ixVolume" + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + required: true + immutable: true + hidden: true + default: "originals" + - variable: aclEntries + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + - variable: hostPathConfig + label: Host Path Configuration + schema: + type: dict + show_if: [["type", "=", "hostPath"]] + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: acl + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + $ref: + - "normalize/acl" + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["aclEnable", "=", false]] + required: true + + - variable: additionalStorages + label: Additional Storage + description: Additional storage for Photoprism. + schema: + type: list + default: [] + items: + - variable: storageEntry + label: Storage Entry + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system.
+ SMB Share: Is a SMB share that is mounted to a persistent volume claim. + schema: + type: string + required: true + default: "ixVolume" + immutable: true + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - value: "smb-pv-pvc" + description: SMB Share (Mounts a persistent volume claim to a SMB share) + - variable: readOnly + label: Read Only + description: Mount the volume as read only. + schema: + type: boolean + default: false + - variable: mountPath + label: Mount Path + description: The path inside the container to mount the storage. + schema: + type: path + required: true + - variable: hostPathConfig + label: Host Path Configuration + schema: + type: dict + show_if: [["type", "=", "hostPath"]] + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: acl + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + $ref: + - "normalize/acl" + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["aclEnable", "=", false]] + required: true + - variable: ixVolumeConfig + label: ixVolume Configuration + description: The configuration for the ixVolume dataset. + schema: + type: dict + show_if: [["type", "=", "ixVolume"]] + $ref: + - "normalize/ixVolume" + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + required: true + immutable: true + default: "storage_entry" + - variable: aclEntries + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + - variable: smbConfig + label: SMB Share Configuration + description: The configuration for the SMB Share. + schema: + type: dict + show_if: [["type", "=", "smb-pv-pvc"]] + attrs: + - variable: server + label: Server + description: The server for the SMB share. + schema: + type: string + required: true + - variable: share + label: Share + description: The share name for the SMB share. + schema: + type: string + required: true + - variable: domain + label: Domain (Optional) + description: The domain for the SMB share. + schema: + type: string + - variable: username + label: Username + description: The username for the SMB share. + schema: + type: string + required: true + - variable: password + label: Password + description: The password for the SMB share. + schema: + type: string + required: true + private: true + - variable: size + label: Size (in Gi) + description: The size of the volume quota. + schema: + type: int + required: true + min: 1 + default: 1 + + - variable: resources + label: Resources Configuration + group: Resources Configuration + schema: + type: dict + attrs: + - variable: limits + label: Limits + schema: + type: dict + attrs: + - variable: cpu + label: CPU + description: CPU limit for Photoprism. + schema: + type: string + max_length: 6 + valid_chars: '^(0\.[1-9]|[1-9][0-9]*)(\.[0-9]|m?)$' + valid_chars_error: | + Valid CPU limit formats are
+ - Plain Integer - eg. 1
+ - Float - eg. 0.5
+ - Milicpu - eg. 500m + default: "4000m" + required: true + - variable: memory + label: Memory + description: Memory limit for Photoprism. + schema: + type: string + max_length: 12 + valid_chars: '^[1-9][0-9]*([EPTGMK]i?|e[0-9]+)?$' + valid_chars_error: | + Valid Memory limit formats are
+ - Suffixed with E/P/T/G/M/K - eg. 1G
+ - Suffixed with Ei/Pi/Ti/Gi/Mi/Ki - eg. 1Gi
+ - Plain Integer in bytes - eg. 1024
+ - Exponent - eg. 134e6 + default: "8Gi" + required: true + + - variable: photoprismGPU + group: Resources Configuration + label: GPU Configuration + schema: + type: dict + $ref: + - "definitions/gpuConfiguration" + attrs: [] diff --git a/charts/photoprism/2.0.0/templates/NOTES.txt b/charts/photoprism/2.0.0/templates/NOTES.txt new file mode 100644 index 0000000000..ba4e01146c --- /dev/null +++ b/charts/photoprism/2.0.0/templates/NOTES.txt @@ -0,0 +1 @@ +{{ include "ix.v1.common.lib.chart.notes" $ }} diff --git a/charts/photoprism/2.0.0/templates/_migration.tpl b/charts/photoprism/2.0.0/templates/_migration.tpl new file mode 100644 index 0000000000..b9e0e23016 --- /dev/null +++ b/charts/photoprism/2.0.0/templates/_migration.tpl @@ -0,0 +1,35 @@ +{{- define "photoprism.get-versions" -}} + {{- $oldChartVersion := "" -}} + {{- $newChartVersion := "" -}} + + {{/* Safely access the context, so it wont block CI */}} + {{- if hasKey .Values.global "ixChartContext" -}} + {{- if .Values.global.ixChartContext.upgradeMetadata -}} + + {{- $oldChartVersion = .Values.global.ixChartContext.upgradeMetadata.oldChartVersion -}} + {{- $newChartVersion = .Values.global.ixChartContext.upgradeMetadata.newChartVersion -}} + {{- if and (not $oldChartVersion) (not $newChartVersion) -}} + {{- fail "Upgrade Metadata is missing. Cannot proceed" -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- toYaml (dict "old" $oldChartVersion "new" $newChartVersion) -}} +{{- end -}} + +{{- define "photoprism.migration" -}} + {{- $versions := (fromYaml (include "photoprism.get-versions" $)) -}} + {{- if and $versions.old $versions.new -}} + {{- $oldV := semver $versions.old -}} + {{- $newV := semver $versions.new -}} + + {{/* If new is v2.x.x */}} + {{- if eq ($newV.Major | int) 2 -}} + {{/* And old is v1.x.x, but lower than .1.3 */}} + {{- if and (eq $oldV.Major 1) (or (ne $oldV.Minor 1) (lt ($oldV.Patch | int) 3)) -}} + {{/* Block the upgrade */}} + {{- fail "Migration to 2.x.x is only allowed from 1.1.3 or higher" -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/charts/photoprism/2.0.0/templates/_persistance.tpl b/charts/photoprism/2.0.0/templates/_persistance.tpl new file mode 100644 index 0000000000..f355fa8e38 --- /dev/null +++ b/charts/photoprism/2.0.0/templates/_persistance.tpl @@ -0,0 +1,40 @@ +{{- define "photoprism.persistence" -}} +persistence: + import: + enabled: true + {{- include "ix.v1.common.app.storageOptions" (dict "storage" .Values.photoprismStorage.import) | nindent 4 }} + targetSelector: + photoprism: + photoprism: + mountPath: /photoprism/import + storage: + enabled: true + {{- include "ix.v1.common.app.storageOptions" (dict "storage" .Values.photoprismStorage.storage) | nindent 4 }} + targetSelector: + photoprism: + photoprism: + mountPath: /photoprism/storage + originals: + enabled: true + {{- include "ix.v1.common.app.storageOptions" (dict "storage" .Values.photoprismStorage.originals) | nindent 4 }} + targetSelector: + photoprism: + photoprism: + mountPath: /photoprism/originals + tmp: + enabled: true + type: emptyDir + targetSelector: + photoprism: + photoprism: + mountPath: /tmp + {{- range $idx, $storage := .Values.photoprismStorage.additionalStorages }} + {{ printf "ha-%v:" (int $idx) }} + enabled: true + {{- include "ix.v1.common.app.storageOptions" (dict "storage" $storage) | nindent 4 }} + targetSelector: + photoprism: + photoprism: + mountPath: {{ $storage.mountPath }} + {{- end }} +{{- end -}} diff --git a/charts/photoprism/2.0.0/templates/_photoprism.tpl b/charts/photoprism/2.0.0/templates/_photoprism.tpl new file mode 100644 index 0000000000..5402a1d688 --- /dev/null +++ b/charts/photoprism/2.0.0/templates/_photoprism.tpl @@ -0,0 +1,74 @@ +{{- define "photoprism.workload" -}} +workload: + photoprism: + enabled: true + primary: true + type: Deployment + podSpec: + hostNetwork: {{ .Values.photoprismNetwork.hostNetwork }} + securityContext: + fsGroup: {{ .Values.photoprismID.group }} + containers: + photoprism: + enabled: true + primary: true + imageSelector: image + securityContext: + runAsUser: 0 + runAsGroup: 0 + runAsNonRoot: false + readOnlyRootFilesystem: false + capabilities: + add: + - CHOWN + - FOWNER + - DAC_OVERRIDE + - SETGID + - SETUID + - KILL + env: + PHOTOPRISM_HTTP_PORT: {{ .Values.photoprismNetwork.webPort }} + PHOTOPRISM_ADMIN_PASSWORD: {{ .Values.photoprismConfig.password }} + PHOTOPRISM_PUBLIC: {{ .Values.photoprismConfig.public }} + PHOTOPRISM_UID: {{ .Values.photoprismID.user }} + PHOTOPRISM_GID: {{ .Values.photoprismID.group }} + PHOTOPRISM_STORAGE_PATH: /photoprism/storage + PHOTOPRISM_ORIGINALS_PATH: /photoprism/originals + PHOTOPRISM_IMPORT_PATH: /photoprism/import + fixedEnv: + PUID: {{ .Values.photoprismID.user }} + {{ with .Values.photoprismConfig.additionalEnvs }} + envList: + {{ range $env := . }} + - name: {{ $env.name }} + value: {{ $env.value }} + {{ end }} + {{ end }} + probes: + liveness: + enabled: true + type: http + path: / + port: {{ .Values.photoprismNetwork.webPort }} + readiness: + enabled: true + type: http + path: / + port: {{ .Values.photoprismNetwork.webPort }} + startup: + enabled: true + type: http + path: / + port: {{ .Values.photoprismNetwork.webPort }} + +{{ with .Values.photoprismGPU }} +scaleGPU: + {{ range $key, $value := . }} + - gpu: + {{ $key }}: {{ $value }} + targetSelector: + photoprism: + - photoprism + {{ end }} +{{ end }} +{{- end -}} diff --git a/charts/photoprism/2.0.0/templates/_portal.tpl b/charts/photoprism/2.0.0/templates/_portal.tpl new file mode 100644 index 0000000000..92f166ddca --- /dev/null +++ b/charts/photoprism/2.0.0/templates/_portal.tpl @@ -0,0 +1,12 @@ +{{- define "photoprism.portal" -}} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: portal +data: + port: {{ .Values.photoprismNetwork.webPort | quote }} + path: "/" + protocol: "http" + host: $node_ip +{{- end -}} diff --git a/charts/photoprism/2.0.0/templates/_service.tpl b/charts/photoprism/2.0.0/templates/_service.tpl new file mode 100644 index 0000000000..0349d29c44 --- /dev/null +++ b/charts/photoprism/2.0.0/templates/_service.tpl @@ -0,0 +1,15 @@ +{{- define "photoprism.service" -}} +service: + photoprism: + enabled: true + primary: true + type: NodePort + targetSelector: photoprism + ports: + webui: + enabled: true + primary: true + port: {{ .Values.photoprismNetwork.webPort }} + nodePort: {{ .Values.photoprismNetwork.webPort }} + targetSelector: photoprism +{{- end -}} diff --git a/charts/photoprism/2.0.0/templates/common.yaml b/charts/photoprism/2.0.0/templates/common.yaml new file mode 100644 index 0000000000..ab446c2d76 --- /dev/null +++ b/charts/photoprism/2.0.0/templates/common.yaml @@ -0,0 +1,13 @@ +{{- include "ix.v1.common.loader.init" . -}} + +{{- include "photoprism.migration" $ -}} + +{{/* Merge the templates with Values */}} +{{- $_ := mustMergeOverwrite .Values (include "photoprism.workload" $ | fromYaml) -}} +{{- $_ := mustMergeOverwrite .Values (include "photoprism.service" $ | fromYaml) -}} +{{- $_ := mustMergeOverwrite .Values (include "photoprism.persistence" $ | fromYaml) -}} + +{{/* Create the configmap for portal manually*/}} +{{- include "photoprism.portal" $ -}} + +{{- include "ix.v1.common.loader.apply" . -}}