From b1ec000492e5b62999fbed8c8b0e6cb9d3bed0c4 Mon Sep 17 00:00:00 2001 From: Stavros Kois <47820033+stavros-k@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:39:28 +0300 Subject: [PATCH] Add `sftpgo` to `community` train (#1601) * initial commit * add metadata * add readme * add common * extend upgrade_strategy * add initial templates * add qs * fix path * fix typo * quote nums * add some integrations * try dobule underscore * add service lists and test variable * update quetsions * double is the one * add passive port range on ftpd * fix webdav * formatting * https * test plugin too * services * remove todo * add data storage * fix portal, ui and services * only if there are defined --- library/ix-dev/community/sftpgo/Chart.lock | 6 + library/ix-dev/community/sftpgo/Chart.yaml | 25 + library/ix-dev/community/sftpgo/README.md | 8 + library/ix-dev/community/sftpgo/app-readme.md | 8 + .../community/sftpgo/charts/common-1.1.1.tgz | Bin 0 -> 61738 bytes .../community/sftpgo/ci/basic-values.yaml | 14 + .../community/sftpgo/ci/https-values.yaml | 97 ++++ .../sftpgo/ci/integrations-values.yaml | 28 ++ .../community/sftpgo/ci/plugin-values.yaml | 31 ++ library/ix-dev/community/sftpgo/item.yaml | 6 + library/ix-dev/community/sftpgo/metadata.yaml | 8 + .../ix-dev/community/sftpgo/questions.yaml | 443 ++++++++++++++++++ .../community/sftpgo/templates/NOTES.txt | 1 + .../sftpgo/templates/_configuration.tpl | 40 ++ .../sftpgo/templates/_persistence.tpl | 78 +++ .../community/sftpgo/templates/_portal.tpl | 16 + .../community/sftpgo/templates/_service.tpl | 18 + .../community/sftpgo/templates/_sftpgo.tpl | 54 +++ .../community/sftpgo/templates/_svcGen.tpl | 53 +++ .../sftpgo/templates/_validation.tpl | 34 ++ .../community/sftpgo/templates/common.yaml | 13 + .../ix-dev/community/sftpgo/upgrade_info.json | 1 + .../ix-dev/community/sftpgo/upgrade_strategy | 48 ++ library/ix-dev/community/sftpgo/values.yaml | 45 ++ 24 files changed, 1075 insertions(+) create mode 100644 library/ix-dev/community/sftpgo/Chart.lock create mode 100644 library/ix-dev/community/sftpgo/Chart.yaml create mode 100644 library/ix-dev/community/sftpgo/README.md create mode 100644 library/ix-dev/community/sftpgo/app-readme.md create mode 100644 library/ix-dev/community/sftpgo/charts/common-1.1.1.tgz create mode 100644 library/ix-dev/community/sftpgo/ci/basic-values.yaml create mode 100644 library/ix-dev/community/sftpgo/ci/https-values.yaml create mode 100644 library/ix-dev/community/sftpgo/ci/integrations-values.yaml create mode 100644 library/ix-dev/community/sftpgo/ci/plugin-values.yaml create mode 100644 library/ix-dev/community/sftpgo/item.yaml create mode 100644 library/ix-dev/community/sftpgo/metadata.yaml create mode 100644 library/ix-dev/community/sftpgo/questions.yaml create mode 100644 library/ix-dev/community/sftpgo/templates/NOTES.txt create mode 100644 library/ix-dev/community/sftpgo/templates/_configuration.tpl create mode 100644 library/ix-dev/community/sftpgo/templates/_persistence.tpl create mode 100644 library/ix-dev/community/sftpgo/templates/_portal.tpl create mode 100644 library/ix-dev/community/sftpgo/templates/_service.tpl create mode 100644 library/ix-dev/community/sftpgo/templates/_sftpgo.tpl create mode 100644 library/ix-dev/community/sftpgo/templates/_svcGen.tpl create mode 100644 library/ix-dev/community/sftpgo/templates/_validation.tpl create mode 100644 library/ix-dev/community/sftpgo/templates/common.yaml create mode 100644 library/ix-dev/community/sftpgo/upgrade_info.json create mode 100755 library/ix-dev/community/sftpgo/upgrade_strategy create mode 100644 library/ix-dev/community/sftpgo/values.yaml diff --git a/library/ix-dev/community/sftpgo/Chart.lock b/library/ix-dev/community/sftpgo/Chart.lock new file mode 100644 index 0000000000..b4e8578727 --- /dev/null +++ b/library/ix-dev/community/sftpgo/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: file://../../../common + version: 1.1.1 +digest: sha256:a7dbe3e4d42dbcd4325776e5e01a1d630c7f185f79e7ebf22b1b9cc80f56eed7 +generated: "2023-10-03T18:09:23.669495026+03:00" diff --git a/library/ix-dev/community/sftpgo/Chart.yaml b/library/ix-dev/community/sftpgo/Chart.yaml new file mode 100644 index 0000000000..a7d5c77b07 --- /dev/null +++ b/library/ix-dev/community/sftpgo/Chart.yaml @@ -0,0 +1,25 @@ +name: sftpgo +description: SFTPGo is a fully featured and highly configurable SFTP server with optional HTTP/S, FTP/S and WebDAV support - S3, Google Cloud Storage, Azure Blob +annotations: + title: SFTPGo +type: application +version: 1.0.0 +apiVersion: v2 +appVersion: v2.5.4 +kubeVersion: '>=1.16.0-0' +maintainers: + - name: truenas + url: https://www.truenas.com/ + email: dev@ixsystems.com +dependencies: + - name: common + repository: file://../../../common + version: 1.1.1 +home: https://github.com/drakkan/sftpgo +icon: https://github.com/drakkan/sftpgo/blob/main/img/logo.png?raw=true +sources: + - https://hub.docker.com/r/drakkan/sftpgo + - https://github.com/truenas/charts/tree/master/library/ix-dev/community/sftpgo + - https://github.com/drakkan/sftpgo +keywords: + - sftpgo diff --git a/library/ix-dev/community/sftpgo/README.md b/library/ix-dev/community/sftpgo/README.md new file mode 100644 index 0000000000..949a127fe1 --- /dev/null +++ b/library/ix-dev/community/sftpgo/README.md @@ -0,0 +1,8 @@ +# SFTPGo + +[SFTPGo](https://github.com/drakkan/sftpgo) is a fully featured and highly configurable SFTP server with optional HTTP/S, FTP/S and WebDAV support - S3, Google Cloud Storage, Azure Blob + +> When application is installed, a container will be launched with **root** privileges. +> This is required in order to apply the correct permissions to the `SFTPGo` directories. +> Afterward, the `SFTPGo` container will run as a **non**-root user (Default: `568`). +> All mounted storage(s) will be `chown`ed only if the parent directory does not match the configured user. diff --git a/library/ix-dev/community/sftpgo/app-readme.md b/library/ix-dev/community/sftpgo/app-readme.md new file mode 100644 index 0000000000..949a127fe1 --- /dev/null +++ b/library/ix-dev/community/sftpgo/app-readme.md @@ -0,0 +1,8 @@ +# SFTPGo + +[SFTPGo](https://github.com/drakkan/sftpgo) is a fully featured and highly configurable SFTP server with optional HTTP/S, FTP/S and WebDAV support - S3, Google Cloud Storage, Azure Blob + +> When application is installed, a container will be launched with **root** privileges. +> This is required in order to apply the correct permissions to the `SFTPGo` directories. +> Afterward, the `SFTPGo` container will run as a **non**-root user (Default: `568`). +> All mounted storage(s) will be `chown`ed only if the parent directory does not match the configured user. diff --git a/library/ix-dev/community/sftpgo/charts/common-1.1.1.tgz b/library/ix-dev/community/sftpgo/charts/common-1.1.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..b739cf1f4657cda28c3d58f50a661b6eb1c9425f GIT binary patch literal 61738 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�<@}Q*O%LCNTm#3%xD6r) zD&_4Zu2R3E3#ak>WtdIS*2M~rALV+{uO&|D#F$AC%QE7--vr?|H3ltRTq8r3`lt>%Q)Fv5#yr4Y^#ZiFLG z^B;!H!O&sowh&3P+GCe=l)LZ8P9_)5%{9jVsupDnZq=^5`qk9TM|k~>F8O^l>$n;Q zRCHuj1@CQ-E57;Hx3PXwY6ABVe^76NSTsRSUiz(oZ~FqkuZj8&(t)QekYl%owrhuj z>fMB86l2NdZ-l&Hrd?TS{xlkh9rgifD!cIM*b^Acmve1i?a$BDE!fJKPRnk&vp+pQ z%TBffwJC;8s!V0w#Y z`X2Q|GmOldHu{iMy@BYseD$N!i_eMhHcxJfyMTZ;n+f!Oo;;gL1-`>4jKBFJmwYzD zbE)UtQN51wrKeK*7nQn?|MtvWR1gxfmNF9mUaO|7bjSJBa-uJ}pLyHm zcUEn+!_`gD{!3TCbZpV&r&v^Sg!+R+VmQ@fxaotLBq zdONP-!1pzyGMvC~wrBxR&y)ft(DQ+f_wc`4(e^w^J_{}g^++FBk9ADDsI2*u;B|l7 zY}8ufAKNA!+qBHC{>j#A*gTZP?`2pV*Bgv3*WBi4;4!o#%V^4A_WD&HjR7B>;H#k7 zT45clgHp-68hGjslF5p{^17PA@qJ1Vu=|cxB?xSZueI!fNFnQqp6{jlM?fyuOqCSF zm5c9G_&bye4&@_)O~d01rdb%?Z)#&b)ypl=0VJja`XJ|-3BOm%!}-^_Wn|-j_VIE*tzN@wu=ps zvP-}xRC$^+lO!nLTVhr9Q^5ZVpOOxw`Zde3=fM^8vjs8IL1-Cw)#v9@bu`XmK}U9 z4#cYwhz}?0`k3WXZZl{@5h&cppu1lj`5pl)t!KitaE{)fzyCdnR5MvGydM z#gz8OPO_Owik03Q@a;v?TU@sT%a57F5=|f>>0X(0u#?%!#*j$mP7XYaC=r%dgnm}% z)GO{`I}R`v;wE4D@$^%vW;%SZe*$I#f&dD~DS%I#1q@;hCn&!*f!k^+{rmazBi!9m z*T+U;o)ungHTziq`do*L0Y;T#z(4Zj!Qa4$xbeYAyi%C;-lgjRmFnnW%1-_asAtP~ zm+7&s<*Co`uOuPr!$Il51siN7OMDWi78F9trT*bkTigBiO6*O0XVN0nbY}bfZi3WX z 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 + schema: + type: boolean + default: false + - variable: certificateID + label: Certificate + description: The certificate to use for SFTPGo WebUI + schema: + type: int + "null": true + $ref: + - "definitions/certificate" + - variable: webPort + label: Web Port + description: The port for the SFTPGo Web UI. + schema: + type: int + default: 30086 + min: 9000 + max: 65535 + required: true + - variable: webdavdServices + label: WebDAVd Services + description: Enable one or more WebDAVd services. + schema: + type: list + default: [] + items: + - variable: webdavdServiceEntry + label: WebDAVd Service Entry + schema: + type: dict + attrs: + - variable: enabled + label: Enabled + description: Enable this WebDAVd service. + schema: + type: boolean + default: false + - variable: port + label: Port + description: The port for WebDAVd. + schema: + type: int + default: 30089 + min: 9000 + max: 65535 + required: true + - variable: sftpdServices + label: SFTPd Services + description: Enable one or more SFTPd services. + schema: + type: list + default: [] + items: + - variable: sftpdServiceEntry + label: SFTPd Service Entry + schema: + type: dict + attrs: + - variable: enabled + label: Enabled + description: Enable this SFTPd service. + schema: + type: boolean + default: false + - variable: port + label: Port + description: The port for SFTPd. + schema: + type: int + default: 30087 + min: 9000 + max: 65535 + required: true + - variable: ftpdServices + label: FTPd Services + description: Enable one or more FTPd services. + schema: + type: list + default: [] + items: + - variable: ftpdServiceEntry + label: FTPd Service Entry + schema: + type: dict + attrs: + - variable: enabled + label: Enabled + description: Enable this FTPd service. + schema: + type: boolean + default: false + - variable: port + label: Port + description: The port for FTPd. + schema: + type: int + default: 30088 + min: 9000 + max: 65535 + required: true + - variable: ftpdPassivePortRange + label: FTPd Passive Port Range + description: The port range for FTPd passive connections. + schema: + type: dict + show_if: [["ftpdServices", "!=", []]] + attrs: + - variable: start + label: Start + description: The start of the port range. + schema: + type: int + default: 50000 + min: 9000 + max: 65535 + required: true + - variable: end + label: End + description: The end of the port range. + schema: + type: int + default: 50001 + min: 9000 + max: 65535 + required: true + + - variable: sftpgoStorage + label: "" + group: Storage Configuration + schema: + type: dict + attrs: + - variable: config + label: SFTPGo Config Storage + description: The path to store SFTPGo Configuration. + 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 + 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: datasetName + label: Dataset Name + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + hidden: true + immutable: true + default: "config" + $ref: + - "normalize/ixVolume" + - variable: hostPath + label: Host Path + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + immutable: true + required: true + - variable: data + label: SFTPGo Data Storage + description: The path to store SFTPGo Data. + 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 + 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: datasetName + label: Dataset Name + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + hidden: true + immutable: true + default: "data" + $ref: + - "normalize/ixVolume" + - variable: hostPath + label: Host Path + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + immutable: true + required: true + - variable: backups + label: SFTPGo Backups Storage + description: The path to store SFTPGo Backups. + 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 + 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: datasetName + label: Dataset Name + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + hidden: true + immutable: true + default: "backups" + $ref: + - "normalize/ixVolume" + - variable: hostPath + label: Host Path + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + immutable: true + required: true + - variable: additionalStorages + label: Additional Storage + description: Additional storage for SFTPGo. + 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. + schema: + type: string + required: 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: mountPath + label: Mount Path + description: The path inside the container to mount the storage. + schema: + type: path + required: true + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + required: true + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + immutable: true + default: "storage_entry" + $ref: + - "normalize/ixVolume" + + - variable: resources + group: Resources Configuration + label: "" + schema: + type: dict + attrs: + - variable: limits + label: Limits + schema: + type: dict + attrs: + - variable: cpu + label: CPU + description: CPU limit for SFTPGo. + 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 SFTPGo. + 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 diff --git a/library/ix-dev/community/sftpgo/templates/NOTES.txt b/library/ix-dev/community/sftpgo/templates/NOTES.txt new file mode 100644 index 0000000000..ba4e01146c --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/NOTES.txt @@ -0,0 +1 @@ +{{ include "ix.v1.common.lib.chart.notes" $ }} diff --git a/library/ix-dev/community/sftpgo/templates/_configuration.tpl b/library/ix-dev/community/sftpgo/templates/_configuration.tpl new file mode 100644 index 0000000000..098208e990 --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/_configuration.tpl @@ -0,0 +1,40 @@ +{{- define "sftpgo.configuration" -}} +configmap: + sftpgo-config: + enabled: true + data: + SFTPGO_CONFIG_DIR: /var/lib/sftpgo + SFTPGO_DATA_PROVIDER__USERS_BASE_DIR: /srv/sftpgo/data + SFTPGO_DATA_PROVIDER__BACKUPS_PATH: /srv/sftpgo/backups + SFTPGO_GRACE_TIME: {{ .Values.sftpgoConfig.graceTime | quote }} + SFTPGO_HTTPD__BINDINGS__0__PORT: {{ .Values.sftpgoNetwork.webPort | quote }} + SFTPGO_HTTPD__BINDINGS__0__ADDRESS: '' + SFTPGO_HTTPD__BINDINGS__0__ENABLE_WEB_ADMIN: "true" + {{- if .Values.sftpgoNetwork.certificateID }} + SFTPGO_HTTPD__BINDINGS__0__ENABLE_HTTPS: "true" + SFTPGO_HTTPD__BINDINGS__0__CERTIFICATE_FILE: /srv/sftpgo/certs/public.crt + SFTPGO_HTTPD__BINDINGS__0__CERTIFICATE_KEY_FILE: /srv/sftpgo/certs/private.key + {{- end -}} + {{/* SFTPD */}} + {{- $enabledServices := (include "sftpgo.svc.enabled" (dict "rootCtx" $ "type" "sftpd") | fromJsonArray) -}} + {{- range $idx, $svc := $enabledServices }} + SFTPGO_SFTPD__BINDINGS__{{ $idx }}__PORT: {{ $svc.port | quote }} + SFTPGO_SFTPD__BINDINGS__{{ $idx }}__ADDRESS: '' + {{- end -}} + {{/* FTPD */}} + {{- $enabledServices := (include "sftpgo.svc.enabled" (dict "rootCtx" $ "type" "ftpd") | fromJsonArray) -}} + {{- range $idx, $svc := $enabledServices }} + SFTPGO_FTPD__BINDINGS__{{ $idx }}__PORT: {{ $svc.port | quote }} + SFTPGO_FTPD__BINDINGS__{{ $idx }}__ADDRESS: '' + {{- end -}} + {{- if $enabledServices }} + SFTPGO_FTPD__PASSIVE_PORT_RANGE__START: {{ .Values.sftpgoNetwork.ftpdPassivePortRange.start | quote }} + SFTPGO_FTPD__PASSIVE_PORT_RANGE__END: {{ .Values.sftpgoNetwork.ftpdPassivePortRange.end | quote }} + {{- end -}} + {{/* WEBDAV */}} + {{- $enabledServices := (include "sftpgo.svc.enabled" (dict "rootCtx" $ "type" "webdavd") | fromJsonArray) -}} + {{- range $idx, $svc := $enabledServices }} + SFTPGO_WEBDAVD__BINDINGS__{{ $idx }}__PORT: {{ $svc.port | quote }} + SFTPGO_WEBDAVD__BINDINGS__{{ $idx }}__ADDRESS: '' + {{- end -}} +{{- end -}} diff --git a/library/ix-dev/community/sftpgo/templates/_persistence.tpl b/library/ix-dev/community/sftpgo/templates/_persistence.tpl new file mode 100644 index 0000000000..fae922fcf1 --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/_persistence.tpl @@ -0,0 +1,78 @@ +{{- define "sftpgo.persistence" -}} +persistence: + config: + enabled: true + type: {{ .Values.sftpgoStorage.config.type }} + datasetName: {{ .Values.sftpgoStorage.config.datasetName | default "" }} + hostPath: {{ .Values.sftpgoStorage.config.hostPath | default "" }} + targetSelector: + sftpgo: + sftpgo: + mountPath: /var/lib/sftpgo + 01-permissions: + mountPath: /mnt/directories/config + data: + enabled: true + type: {{ .Values.sftpgoStorage.data.type }} + datasetName: {{ .Values.sftpgoStorage.data.datasetName | default "" }} + hostPath: {{ .Values.sftpgoStorage.data.hostPath | default "" }} + targetSelector: + sftpgo: + sftpgo: + mountPath: /srv/sftpgo/data + 01-permissions: + mountPath: /mnt/directories/data + backups: + enabled: true + type: {{ .Values.sftpgoStorage.backups.type }} + datasetName: {{ .Values.sftpgoStorage.backups.datasetName | default "" }} + hostPath: {{ .Values.sftpgoStorage.backups.hostPath | default "" }} + targetSelector: + sftpgo: + sftpgo: + mountPath: /srv/sftpgo/backups + 01-permissions: + mountPath: /mnt/directories/backups + tmp: + enabled: true + type: emptyDir + targetSelector: + sftpgo: + sftpgo: + mountPath: /tmp + {{- range $idx, $storage := .Values.sftpgoStorage.additionalStorages }} + {{ printf "sftpgo-%v" (int $idx) }}: + enabled: true + type: {{ $storage.type }} + datasetName: {{ $storage.datasetName | default "" }} + hostPath: {{ $storage.hostPath | default "" }} + targetSelector: + sftpgo: + sftpgo: + mountPath: {{ $storage.mountPath }} + 01-permissions: + mountPath: /mnt/directories{{ $storage.mountPath }} + {{- end -}} + {{- if .Values.sftpgoNetwork.certificateID }} + cert: + enabled: true + type: secret + objectName: sftpgo-cert + defaultMode: "0600" + items: + - key: tls.key + path: private.key + - key: tls.crt + path: public.crt + targetSelector: + sftpgo: + sftpgo: + mountPath: /srv/sftpgo/certs + readOnly: true + +scaleCertificate: + sftpgo-cert: + enabled: true + id: {{ .Values.sftpgoNetwork.certificateID }} + {{- end -}} +{{- end -}} diff --git a/library/ix-dev/community/sftpgo/templates/_portal.tpl b/library/ix-dev/community/sftpgo/templates/_portal.tpl new file mode 100644 index 0000000000..c6d30354c2 --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/_portal.tpl @@ -0,0 +1,16 @@ +{{- define "sftpgo.portal" -}} +{{- $protocol := "http" -}} +{{- if .Values.sftpgoNetwork.certificateID -}} + {{- $protocol = "https" -}} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: portal +data: + path: "/web/admin" + port: {{ .Values.sftpgoNetwork.webPort | quote }} + protocol: {{ $protocol | quote }} + host: $node_ip +{{- end -}} diff --git a/library/ix-dev/community/sftpgo/templates/_service.tpl b/library/ix-dev/community/sftpgo/templates/_service.tpl new file mode 100644 index 0000000000..1cca42836e --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/_service.tpl @@ -0,0 +1,18 @@ +{{- define "sftpgo.service" -}} +service: + sftpgo: + enabled: true + primary: true + type: NodePort + targetSelector: sftpgo + ports: + webui: + enabled: true + primary: true + port: {{ .Values.sftpgoNetwork.webPort }} + nodePort: {{ .Values.sftpgoNetwork.webPort }} + targetSelector: sftpgo + {{- include "sftpgo.svc.gen" (dict "rootCtx" $ "type" "sftpd") | nindent 2 }} + {{- include "sftpgo.svc.gen" (dict "rootCtx" $ "type" "ftpd") | nindent 2 }} + {{- include "sftpgo.svc.gen" (dict "rootCtx" $ "type" "webdavd") | nindent 2 }} +{{- end -}} diff --git a/library/ix-dev/community/sftpgo/templates/_sftpgo.tpl b/library/ix-dev/community/sftpgo/templates/_sftpgo.tpl new file mode 100644 index 0000000000..34f65caa7a --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/_sftpgo.tpl @@ -0,0 +1,54 @@ +{{- define "sftpgo.workload" -}} +workload: + sftpgo: + enabled: true + primary: true + type: Deployment + podSpec: + hostNetwork: {{ .Values.sftpgoNetwork.hostNetwork }} + terminationGracePeriodSeconds: {{ .Values.sftpgoConfig.graceTime }} + containers: + sftpgo: + enabled: true + primary: true + imageSelector: image + securityContext: + runAsUser: {{ .Values.sftpgoRunAs.user }} + runAsGroup: {{ .Values.sftpgoRunAs.group }} + envFrom: + - configMapRef: + name: sftpgo-config + {{ with .Values.sftpgoConfig.additionalEnvs }} + envList: + {{ range $env := . }} + - name: {{ $env.name }} + value: {{ $env.value }} + {{ end }} + {{ end }} + probes: + {{- $protocol := "http" -}} + {{- if .Values.sftpgoNetwork.certificateID -}} + {{- $protocol = "https" -}} + {{- end }} + liveness: + enabled: true + type: {{ $protocol }} + port: {{ .Values.sftpgoNetwork.webPort }} + path: /healthz + readiness: + enabled: true + type: {{ $protocol }} + port: {{ .Values.sftpgoNetwork.webPort }} + path: /healthz + startup: + enabled: true + type: {{ $protocol }} + port: {{ .Values.sftpgoNetwork.webPort }} + path: /healthz + initContainers: + {{- include "ix.v1.common.app.permissions" (dict "containerName" "01-permissions" + "UID" .Values.sftpgoRunAs.user + "GID" .Values.sftpgoRunAs.group + "mode" "check" + "type" "init") | nindent 8 }} +{{- end -}} diff --git a/library/ix-dev/community/sftpgo/templates/_svcGen.tpl b/library/ix-dev/community/sftpgo/templates/_svcGen.tpl new file mode 100644 index 0000000000..a80216671c --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/_svcGen.tpl @@ -0,0 +1,53 @@ +{{- define "sftpgo.svc.gen" -}} + {{- $rootCtx := .rootCtx -}} + {{- $type := .type -}} + + {{- $enabledServices := (include "sftpgo.svc.enabled" (dict "rootCtx" $rootCtx "type" $type) | fromJsonArray) -}} + +{{- with $enabledServices }} +{{ printf "sftpgo-%s" $type }}: + enabled: true + type: NodePort + targetSelector: sftpgo + ports: +{{- end -}} + {{- range $idx, $svc := $enabledServices }} + {{ printf "%s-%d" $type $idx }}: + enabled: true + primary: {{ eq ($idx | int) 0 }} + port: {{ $svc.port }} + nodePort: {{ $svc.port }} + targetSelector: sftpgo + {{- end -}} + {{- if and $enabledServices (eq $type "ftpd") -}} + {{- $start := int $rootCtx.Values.sftpgoNetwork.ftpdPassivePortRange.start -}} + {{- $end := int $rootCtx.Values.sftpgoNetwork.ftpdPassivePortRange.end -}} + {{- $end = int (add1 $end) -}} + + {{- range $idx := untilStep $start $end 1 }} + {{ printf "ftpd-pasv-%d" $idx }}: + enabled: true + port: {{ $idx }} + nodePort: {{ $idx }} + targetSelector: sftpgo + {{- end -}} + {{- end -}} +{{- end -}} + +{{- define "sftpgo.svc.enabled" -}} + {{- $rootCtx := .rootCtx -}} + {{- $type := .type -}} + + {{- $services := (get $rootCtx.Values.sftpgoNetwork (printf "%sServices" $type)) -}} + + {{- $enabledServices := list -}} + {{- if $services -}} + {{- range $idx, $svc := $services -}} + {{- if $svc.enabled -}} + {{- $enabledServices = append $enabledServices $svc -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- $enabledServices | toJson -}} +{{- end -}} diff --git a/library/ix-dev/community/sftpgo/templates/_validation.tpl b/library/ix-dev/community/sftpgo/templates/_validation.tpl new file mode 100644 index 0000000000..dc5bd28f10 --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/_validation.tpl @@ -0,0 +1,34 @@ +{{- define "sftgo.validation" -}} + {{- $ports := list -}} + {{- $ports = append $ports .Values.sftpgoNetwork.webPort -}} + + {{- range $k, $v := .Values.sftpgoNetwork -}} + {{- if (hasSuffix "Services" $k) -}} + {{- range $idx, $svc := $v -}} + {{- if $svc.enabled -}} + {{- $ports = append $ports $svc.port -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if gt (len $ports) 20 -}} {{/* Arbitrary limit, to avoid overallocating ports */}} + {{- fail (printf "SFTPGo - Too many ports defined, max 20 ports can be defined [%s]" (join ", " $ports)) -}} + {{- end -}} + + {{- if not (deepEqual ($ports | uniq) $ports) -}} + {{- fail (printf "SFTPGo - Expected ports to be unique for all services, ports defined [%s]" (join ", " $ports)) -}} + {{- end -}} + + {{- if .Values.sftpgoNetwork.ftpdServices -}} + {{- with .Values.sftpgoNetwork.ftpdPassivePortRange -}} + {{- if ge (int .start) (int .end) -}} + {{- fail (printf "SFTPGo - ftpd passive port range start [%d] must be less than end [%d]" (int .start) (int .end)) -}} + {{- end -}} + + {{- if ge (sub (int .end) (int .start)) 20 -}} {{/* Arbitrary limit, to avoid overallocating ports */}} + {{- fail (printf "SFTPGo - ftpd passive port range must be less than 20 ports, start [%d] end [%d]" (int .start) (int .end)) -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/library/ix-dev/community/sftpgo/templates/common.yaml b/library/ix-dev/community/sftpgo/templates/common.yaml new file mode 100644 index 0000000000..2ddf49440d --- /dev/null +++ b/library/ix-dev/community/sftpgo/templates/common.yaml @@ -0,0 +1,13 @@ +{{- include "ix.v1.common.loader.init" . -}} + +{{- include "sftgo.validation" $ -}} +{{/* Merge the templates with Values */}} +{{- $_ := mustMergeOverwrite .Values (include "sftpgo.configuration" $ | fromYaml) -}} +{{- $_ := mustMergeOverwrite .Values (include "sftpgo.service" $ | fromYaml) -}} +{{- $_ := mustMergeOverwrite .Values (include "sftpgo.persistence" $ | fromYaml) -}} +{{- $_ := mustMergeOverwrite .Values (include "sftpgo.workload" $ | fromYaml) -}} + +{{/* Create the configmap for portal manually*/}} +{{- include "sftpgo.portal" $ -}} + +{{- include "ix.v1.common.loader.apply" . -}} diff --git a/library/ix-dev/community/sftpgo/upgrade_info.json b/library/ix-dev/community/sftpgo/upgrade_info.json new file mode 100644 index 0000000000..767388094a --- /dev/null +++ b/library/ix-dev/community/sftpgo/upgrade_info.json @@ -0,0 +1 @@ +{"filename": "values.yaml", "keys": ["image"]} diff --git a/library/ix-dev/community/sftpgo/upgrade_strategy b/library/ix-dev/community/sftpgo/upgrade_strategy new file mode 100755 index 0000000000..54f5603e4c --- /dev/null +++ b/library/ix-dev/community/sftpgo/upgrade_strategy @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +import json +import re +import sys + +from catalog_update.upgrade_strategy import semantic_versioning + +RE_STABLE_VERSION_BASE = r'v\d+\.\d+\.\d+' +ENUMS = { + 'image': { + 'RE_STABLE_VERSION': re.compile(rf'{RE_STABLE_VERSION_BASE}'), + }, + 'pluginsImage': { + 'RE_STABLE_VERSION': re.compile(rf'{RE_STABLE_VERSION_BASE}-plugins'), + }, +} + + +def newer_mapping(image_tags): + output = { + "tags": {}, + "app_version": "" + } + + for key in image_tags.keys(): + RE_STABLE_VERSION = ENUMS[key].get('RE_STABLE_VERSION', None) if key in ENUMS else None + + tags = {t.strip('v').strip('-plugins'): t for t in image_tags[key] if RE_STABLE_VERSION.fullmatch(t)} + version = semantic_versioning(list(tags)) + + if not version: + continue + + if key == 'image': + output['app_version'] = version + + output['tags'][key] = tags[version] + + return output + + +if __name__ == '__main__': + try: + versions_json = json.loads(sys.stdin.read()) + except ValueError: + raise ValueError('Invalid json specified') + + print(json.dumps(newer_mapping(versions_json))) diff --git a/library/ix-dev/community/sftpgo/values.yaml b/library/ix-dev/community/sftpgo/values.yaml new file mode 100644 index 0000000000..9097c00099 --- /dev/null +++ b/library/ix-dev/community/sftpgo/values.yaml @@ -0,0 +1,45 @@ +image: + repository: drakkan/sftpgo + pullPolicy: IfNotPresent + tag: v2.5.4 +pluginsImage: + repository: drakkan/sftpgo + pullPolicy: IfNotPresent + tag: v2.5.4-plugins + +resources: + limits: + cpu: 4000m + memory: 8Gi + +sftpgoConfig: + imageSelector: image + graceTime: 60 + additionalEnvs: [] + +sftpgoNetwork: + hostNetwork: false + certificateID: + webPort: 30086 + webdavdServices: [] + sftpdServices: [] + ftpdServices: [] + ftpdPassivePortRange: + start: 50000 + end: 50001 + +sftpgoRunAs: + user: 568 + group: 568 + +sftpgoStorage: + config: + type: ixVolume + datasetName: config + data: + type: ixVolume + datasetName: data + backups: + type: ixVolume + datasetName: backups + additionalStorages: []