From 3e75be5fa879bafd8e64678cea5b1f6543cf93a1 Mon Sep 17 00:00:00 2001 From: Stavros Kois <47820033+stavros-k@users.noreply.github.com> Date: Tue, 30 May 2023 16:26:55 +0300 Subject: [PATCH] NAS-119343 / 23.10 / add tftpd-hpa (#1195) * fix a bug in common in regards to sysctls * add netboot * switch to tftp container * perm -> owner * make small adjustment in permission common container * update questions * 2 tests * no double bump * update readme * update readmes * test app * umask * capability * update chmod and readmes * remove test app and update metadata * untouch * update readme * update questions * update strategy * Address review * update image --- .github/workflows/charts_tests.yaml | 4 +- .github/workflows/common_library_tests.yaml | 6 +- .../tests/pod/securityContext.yaml | 37 +++++ library/common/Chart.yaml | 2 +- .../templates/app_functions/_permissions.tpl | 45 +++-- .../templates/lib/pod/_podSecurityContext.tpl | 10 +- library/ix-dev/community/tftpd-hpa/Chart.lock | 6 + library/ix-dev/community/tftpd-hpa/Chart.yaml | 26 +++ library/ix-dev/community/tftpd-hpa/README.md | 14 ++ .../ix-dev/community/tftpd-hpa/app-readme.md | 14 ++ .../tftpd-hpa/charts/common-1.0.8.tgz | Bin 0 -> 55451 bytes .../community/tftpd-hpa/ci/create-values.yaml | 6 + .../tftpd-hpa/ci/readonly-values.yaml | 6 + library/ix-dev/community/tftpd-hpa/item.yaml | 6 + .../ix-dev/community/tftpd-hpa/metadata.yaml | 16 ++ .../ix-dev/community/tftpd-hpa/questions.yaml | 155 ++++++++++++++++++ .../community/tftpd-hpa/templates/NOTES.txt | 1 + .../community/tftpd-hpa/templates/_tftp.tpl | 102 ++++++++++++ .../community/tftpd-hpa/templates/common.yaml | 6 + .../community/tftpd-hpa/upgrade_info.json | 1 + .../community/tftpd-hpa/upgrade_strategy | 30 ++++ .../ix-dev/community/tftpd-hpa/values.yaml | 21 +++ 22 files changed, 494 insertions(+), 20 deletions(-) create mode 100644 library/ix-dev/community/tftpd-hpa/Chart.lock create mode 100644 library/ix-dev/community/tftpd-hpa/Chart.yaml create mode 100644 library/ix-dev/community/tftpd-hpa/README.md create mode 100644 library/ix-dev/community/tftpd-hpa/app-readme.md create mode 100644 library/ix-dev/community/tftpd-hpa/charts/common-1.0.8.tgz create mode 100644 library/ix-dev/community/tftpd-hpa/ci/create-values.yaml create mode 100644 library/ix-dev/community/tftpd-hpa/ci/readonly-values.yaml create mode 100644 library/ix-dev/community/tftpd-hpa/item.yaml create mode 100644 library/ix-dev/community/tftpd-hpa/metadata.yaml create mode 100644 library/ix-dev/community/tftpd-hpa/questions.yaml create mode 100644 library/ix-dev/community/tftpd-hpa/templates/NOTES.txt create mode 100644 library/ix-dev/community/tftpd-hpa/templates/_tftp.tpl create mode 100644 library/ix-dev/community/tftpd-hpa/templates/common.yaml create mode 100644 library/ix-dev/community/tftpd-hpa/upgrade_info.json create mode 100755 library/ix-dev/community/tftpd-hpa/upgrade_strategy create mode 100644 library/ix-dev/community/tftpd-hpa/values.yaml diff --git a/.github/workflows/charts_tests.yaml b/.github/workflows/charts_tests.yaml index 65b99e3e55..640fc768f4 100644 --- a/.github/workflows/charts_tests.yaml +++ b/.github/workflows/charts_tests.yaml @@ -20,7 +20,7 @@ jobs: helm-version: - v3.9.4 - v3.10.3 - - v3.11.3 + - v3.12.0 steps: - name: Checkout uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3 @@ -87,7 +87,7 @@ jobs: # We run tests on Helm version of latest SCALE release, SCALE nightly and manually defined "latest" helm-version: - v3.9.4 - - v3.11.3 + - v3.12.0 # We run tests on k3s version of latest SCALE release, SCALE nightly and manually defined "latest" k3s-version: - v1.25.3+k3s1 diff --git a/.github/workflows/common_library_tests.yaml b/.github/workflows/common_library_tests.yaml index a8c9c7fc50..cde33cb063 100644 --- a/.github/workflows/common_library_tests.yaml +++ b/.github/workflows/common_library_tests.yaml @@ -19,7 +19,7 @@ jobs: helm-version: - v3.9.4 - v3.10.3 - - v3.11.1 + - v3.12.0 steps: - name: Checkout uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3 @@ -57,7 +57,7 @@ jobs: helm-version: - v3.9.4 - v3.10.3 - - v3.11.1 + - v3.12.0 steps: - name: Checkout uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3 @@ -97,7 +97,7 @@ jobs: - v1.25.3+k3s1 # We run tests on Helm version of latest SCALE release, SCALE nightly and manually defined "latest" helm-version: - - v3.11.1 + - v3.12.0 values: - basic-values.yaml - configmap-values.yaml diff --git a/library/common-test/tests/pod/securityContext.yaml b/library/common-test/tests/pod/securityContext.yaml index 6da8baaaa3..6fcae6982b 100644 --- a/library/common-test/tests/pod/securityContext.yaml +++ b/library/common-test/tests/pod/securityContext.yaml @@ -220,6 +220,43 @@ tests: - name: net.ipv4.ip_unprivileged_port_start value: "443" + - it: should pass with sysctls net.ipv4.ip_unprivileged_port_start NOT appended with hostnet + set: + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: + hostNetwork: true + workload-name2: + enabled: true + type: Deployment + podSpec: {} + service: + service-name: + enabled: true + primary: true + type: ClusterIP + targetSelector: workload-name2 + ports: + port-name: + enabled: true + primary: true + port: 443 + asserts: + - documentIndex: &deploymentDoc 0 + isKind: + of: Deployment + - documentIndex: *deploymentDoc + equal: + path: spec.template.spec.securityContext + value: + fsGroup: 568 + fsGroupChangePolicy: OnRootMismatch + supplementalGroups: [] + sysctls: [] + - it: should pass with fsGroup 0 set: securityContext: diff --git a/library/common/Chart.yaml b/library/common/Chart.yaml index a1d497477e..82c1183773 100644 --- a/library/common/Chart.yaml +++ b/library/common/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: common description: A library chart for iX Official Catalog type: library -version: 1.0.7 +version: 1.0.8 appVersion: v1 annotations: title: Common Library Chart diff --git a/library/common/templates/app_functions/_permissions.tpl b/library/common/templates/app_functions/_permissions.tpl index afbc8d8f26..da7370eabf 100644 --- a/library/common/templates/app_functions/_permissions.tpl +++ b/library/common/templates/app_functions/_permissions.tpl @@ -10,6 +10,7 @@ GID: GID to change permissions to {{- $type := .type | default "install" -}} {{- $containerName := .containerName | default "permissions" -}} {{- $mode := .mode | default "always" -}} + {{- $chmod := .chmod | default "" -}} {{- $UID := .UID -}} {{- $GID := .GID -}} @@ -47,6 +48,9 @@ GID: GID to change permissions to capabilities: add: - CHOWN + {{- if $chmod }} + - FOWNER + {{- end }} command: bash args: - -c @@ -57,30 +61,51 @@ GID: GID to change permissions to continue fi - echo "Current Permissions on ["$dir"]:" - stat -c "%u %g" "$dir" + echo "Current Ownership and Permissions on ["$dir"]:" + echo "chown: $(stat -c "%u %g" "$dir")" + echo "chmod: $(stat -c "%a" "$dir")" {{- if eq $mode "check" }} {{/* If mode is check, check parent dir */}} if [ $(stat -c %u "$dir") -eq {{ $UID }} ] && [ $(stat -c %g "$dir") -eq {{ $GID }} ]; then - echo "Permissions are correct. Skipping..." - fix_perms="false" + echo "Ownership is correct. Skipping..." + fix_owner="false" else - echo "Permissions are incorrect. Fixing..." - fix_perms="true" + echo "Ownership is incorrect. Fixing..." + fix_owner="true" fi + {{- if $chmod }} {{/* Only if chmod value is given */}} + if [ $(stat -c %a "$dir") -eq {{ $chmod }} ]; then + echo "Permissions are correct. Skipping..." + fix_perms="false" + else + echo "Permissions are incorrect. Fixing..." + fix_perms="true" + fi + {{- end }} + {{- else if eq $mode "always" }} {{/* If mode is always, always fix perms */}} - + fix_owner="true" fix_perms="true" - {{- end }} - if [ "$fix_perms" = "true" ]; then + {{/* Apply changes */}} + if [ "$fix_owner" = "true" ]; then echo "Changing ownership to {{ $UID }}:{{ $GID }} on: ["$dir"]" chown -R {{ $UID }}:{{ $GID }} "$dir" echo "Finished changing ownership" - echo "Permissions after changing ownership:" + echo "Ownership after changes:" stat -c "%u %g" "$dir" fi + + {{- if $chmod }} {{/* Only if chmod value is given */}} + if [ "$fix_perms" = "true" ]; then + echo "Changing permissions to {{ $chmod }} on: ["$dir"]" + chmod -R {{ $chmod }} "$dir" + echo "Finished changing permissions" + echo "Permissions after changes:" + stat -c "%a" "$dir" + fi + {{- end }} done {{- end -}} diff --git a/library/common/templates/lib/pod/_podSecurityContext.tpl b/library/common/templates/lib/pod/_podSecurityContext.tpl index 9204db3413..9667619258 100644 --- a/library/common/templates/lib/pod/_podSecurityContext.tpl +++ b/library/common/templates/lib/pod/_podSecurityContext.tpl @@ -15,13 +15,13 @@ objectData: The object data to be used to render the Pod. {{/* Initialize from the "global" option */}} {{- $secContext := mustDeepCopy $rootCtx.Values.securityContext.pod -}} - {{/* Override with pod's option */}} + {{/* Override with pods option */}} {{- with $objectData.podSpec.securityContext -}} {{- $secContext = mustMergeOverwrite $secContext . -}} {{- end -}} {{/* TODO: Add supplemental groups - devices (5, 10, 20, 24) (Only when devices is assigned on the pod's containers) + devices (5, 10, 20, 24) (Only when devices is assigned on the pods containers) TODO: Unit Test the above cases */}} @@ -32,7 +32,7 @@ objectData: The object data to be used to render the Pod. {{- if mustHas $objectData.shortName ($GPUValues.targetSelector | keys) -}} {{- $gpuAdded = true -}} {{- end -}} - {{/* If there isn't a selector, but pod is primary */}} + {{/* If there isnt a selector, but pod is primary */}} {{- else if $objectData.primary -}} {{- $gpuAdded = true -}} {{- end -}} @@ -44,7 +44,9 @@ objectData: The object data to be used to render the Pod. {{- $portRange := fromJson (include "ix.v1.common.lib.helpers.securityContext.getPortRange" (dict "rootCtx" $rootCtx "objectData" $objectData)) -}} {{- if and $portRange.low (le (int $portRange.low) 1024) -}} {{/* If a container wants to bind a port <= 1024 change the unprivileged_port_start */}} - {{- $_ := set $secContext "sysctls" (mustAppend $secContext.sysctls (dict "name" "net.ipv4.ip_unprivileged_port_start" "value" (printf "%v" $portRange.low))) -}} + {{- if ne (include "ix.v1.common.lib.pod.hostNetwork" (dict "rootCtx" $rootCtx "objectData" $objectData)) "true" -}} + {{- $_ := set $secContext "sysctls" (mustAppend $secContext.sysctls (dict "name" "net.ipv4.ip_unprivileged_port_start" "value" (printf "%v" $portRange.low))) -}} + {{- end -}} {{- end -}} {{- if or (kindIs "invalid" $secContext.fsGroup) (eq (toString $secContext.fsGroup) "") -}} diff --git a/library/ix-dev/community/tftpd-hpa/Chart.lock b/library/ix-dev/community/tftpd-hpa/Chart.lock new file mode 100644 index 0000000000..15552d20da --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: file://../../../common + version: 1.0.8 +digest: sha256:254efaa1285f634b7a80b7baadeadbd20a680f7fee49d1d9d3c4618aa0d657ad +generated: "2023-05-15T16:04:33.567206466+03:00" diff --git a/library/ix-dev/community/tftpd-hpa/Chart.yaml b/library/ix-dev/community/tftpd-hpa/Chart.yaml new file mode 100644 index 0000000000..15963505c5 --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/Chart.yaml @@ -0,0 +1,26 @@ +name: tftpd-hpa +description: A lightweight tftp-server +annotations: + title: TFTP Server +type: application +version: 1.0.0 +apiVersion: v2 +appVersion: 1.0.0 +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.0.8 +home: https://github.com/truenas/containers/tree/main/apps/tftpd-hpa +icon: https://avatars.githubusercontent.com/u/53482242 +sources: + - https://github.com/truenas/containers/tree/main/apps/tftpd-hpa + - https://github.com/truenas/charts/tree/master/community/tftpd-hpa + - https://hub.docker.com/r/ixsystems/tftpd-hpa +keywords: + - tftp + - netboot diff --git a/library/ix-dev/community/tftpd-hpa/README.md b/library/ix-dev/community/tftpd-hpa/README.md new file mode 100644 index 0000000000..48458faf5c --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/README.md @@ -0,0 +1,14 @@ +# TFTP + +[TFTP](https://manpages.debian.org/testing/tftpd-hpa/tftpd.8.en.html) is a server for the Trivial File Transfer Protocol. + +The app runs as `root` user and drops privileges to `tftp` (9069) user for the TFTP service. + +> On every application start, a container will be launched with **root** privileges. +> This will check the parent directory permissions and ownership. +> If there is a mismatch it will apply the correct permissions to the TFTP directories. +> When "Allow Create" is checked, the above container will also check and `chmod` if needed +> to `757` the TFTP directories and to `555` when not checked. +> Afterward, the `TFTP` container will run as a **root** user, dropping privileges +> to `tftp` (9069) user for the TFTP service. +> Note: You need to have configured DHCP server for network boot to work. diff --git a/library/ix-dev/community/tftpd-hpa/app-readme.md b/library/ix-dev/community/tftpd-hpa/app-readme.md new file mode 100644 index 0000000000..48458faf5c --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/app-readme.md @@ -0,0 +1,14 @@ +# TFTP + +[TFTP](https://manpages.debian.org/testing/tftpd-hpa/tftpd.8.en.html) is a server for the Trivial File Transfer Protocol. + +The app runs as `root` user and drops privileges to `tftp` (9069) user for the TFTP service. + +> On every application start, a container will be launched with **root** privileges. +> This will check the parent directory permissions and ownership. +> If there is a mismatch it will apply the correct permissions to the TFTP directories. +> When "Allow Create" is checked, the above container will also check and `chmod` if needed +> to `757` the TFTP directories and to `555` when not checked. +> Afterward, the `TFTP` container will run as a **root** user, dropping privileges +> to `tftp` (9069) user for the TFTP service. +> Note: You need to have configured DHCP server for network boot to work. diff --git a/library/ix-dev/community/tftpd-hpa/charts/common-1.0.8.tgz b/library/ix-dev/community/tftpd-hpa/charts/common-1.0.8.tgz new file mode 100644 index 0000000000000000000000000000000000000000..68abac5c10fa6b0ee4774ea2ca1b7b1323226a95 GIT binary patch literal 55451 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 literal 0 HcmV?d00001 diff --git a/library/ix-dev/community/tftpd-hpa/ci/create-values.yaml b/library/ix-dev/community/tftpd-hpa/ci/create-values.yaml new file mode 100644 index 0000000000..cb5d2b9113 --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/ci/create-values.yaml @@ -0,0 +1,6 @@ +tftpStorage: + tftpboot: + type: hostPath + hostPath: /mnt/{{ .Release.Name }}/tftpboot +tftpConfig: + allowCreate: true diff --git a/library/ix-dev/community/tftpd-hpa/ci/readonly-values.yaml b/library/ix-dev/community/tftpd-hpa/ci/readonly-values.yaml new file mode 100644 index 0000000000..3b23db6b2a --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/ci/readonly-values.yaml @@ -0,0 +1,6 @@ +tftpStorage: + tftpboot: + type: hostPath + hostPath: /mnt/{{ .Release.Name }}/tftpboot +tftpConfig: + allowCreate: false diff --git a/library/ix-dev/community/tftpd-hpa/item.yaml b/library/ix-dev/community/tftpd-hpa/item.yaml new file mode 100644 index 0000000000..493c2eae43 --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/item.yaml @@ -0,0 +1,6 @@ +icon_url: https://avatars.githubusercontent.com/u/53482242 +screenshots: [] +categories: + - networking +tags: + - tftp diff --git a/library/ix-dev/community/tftpd-hpa/metadata.yaml b/library/ix-dev/community/tftpd-hpa/metadata.yaml new file mode 100644 index 0000000000..ff86e6ead8 --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/metadata.yaml @@ -0,0 +1,16 @@ +runAsContext: + - userName: root + groupName: root + gid: 0 + uid: 0 + description: TFTP requires root privileges to start it's processes. +capabilities: + - name: NET_BIND_SERVICE + description: TFTP requires this ability to bind to port 69 for TFTP. + - name: SETUID + description: TFTP requires this ability to switch user for sub-processes. + - name: SETGID + description: TFTP requires this ability to switch group for sub-processes. + - name: SYS_CHROOT + description: TFTP requires this ability to use chroot for it's sub-processes. +hostMounts: [] diff --git a/library/ix-dev/community/tftpd-hpa/questions.yaml b/library/ix-dev/community/tftpd-hpa/questions.yaml new file mode 100644 index 0000000000..8d852d747e --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/questions.yaml @@ -0,0 +1,155 @@ +groups: + - name: TFTP Configuration + description: Configure TFTP + - name: Network Configuration + description: Configure Network for TFTP + - name: Storage Configuration + description: Configure Storage for TFTP + - name: Resources Configuration + description: Configure Resources for TFTP + +questions: + - variable: TZ + group: TFTP Configuration + label: Timezone + schema: + type: string + default: Etc/UTC + required: true + $ref: + - definitions/timezone + + - variable: tftpConfig + label: "" + group: TFTP Configuration + schema: + type: dict + attrs: + - variable: allowCreate + label: Allow Create + description: | + Allow new files to be created. This is disabled by default.
+ Enabling this will change the permissions of the tftpboot directory to 757. + Disabling this will change the permissions of the tftpboot directory to 555. + schema: + type: boolean + default: false + - variable: additionalEnvs + label: Additional Environment Variables + description: Configure additional environment variables for TFTP. + 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: tftpNetwork + label: "" + group: Network Configuration + schema: + type: dict + attrs: + - variable: hostNetwork + label: Host Network + description: | + Bind to the host network. It's recommended to keep this disabled.
+ schema: + type: boolean + default: true + - variable: tftpPort + label: TFTP Port + description: | + The port for TFTP. + When hostNetwork is enabled, the port tftp port will be 69. + schema: + type: int + default: 30000 + show_if: [["hostNetwork", "=", false]] + min: 9000 + max: 65535 + required: true + + - variable: tftpStorage + label: "" + group: Storage Configuration + schema: + type: dict + attrs: + - variable: tftpboot + label: TFTP Boot Storage + description: The path to store TFTP Boot files. + 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: "tftpboot" + $ref: + - "normalize/ixVolume" + - variable: hostPath + label: Host Path + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + immutable: true + required: true + + - 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 TFTP. + schema: + type: string + default: "4000m" + required: true + - variable: memory + label: Memory + description: Memory limit for TFTP. + schema: + type: string + default: "8Gi" + required: true diff --git a/library/ix-dev/community/tftpd-hpa/templates/NOTES.txt b/library/ix-dev/community/tftpd-hpa/templates/NOTES.txt new file mode 100644 index 0000000000..ba4e01146c --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/templates/NOTES.txt @@ -0,0 +1 @@ +{{ include "ix.v1.common.lib.chart.notes" $ }} diff --git a/library/ix-dev/community/tftpd-hpa/templates/_tftp.tpl b/library/ix-dev/community/tftpd-hpa/templates/_tftp.tpl new file mode 100644 index 0000000000..fee1b44fc3 --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/templates/_tftp.tpl @@ -0,0 +1,102 @@ +{{- define "tftp.workload" -}} +workload: + tftp: + enabled: true + primary: true + type: Deployment + podSpec: + hostNetwork: {{ .Values.tftpNetwork.hostNetwork }} + containers: + tftp: + enabled: true + primary: true + imageSelector: image + securityContext: + runAsUser: 0 + runAsGroup: 0 + runAsNonRoot: false + readOnlyRootFilesystem: false + capabilities: + add: + - NET_BIND_SERVICE + - SETGID + - SETUID + - SYS_CHROOT + env: + MAPFILE: "" + SECURE: "1" + CREATE: {{ ternary "1" "0" .Values.tftpConfig.allowCreate | quote }} + fixedEnv: + UMASK: {{ ternary "020" "" .Values.tftpConfig.allowCreate | quote }} + {{ with .Values.tftpConfig.additionalEnvs }} + envList: + {{ range $env := . }} + - name: {{ $env.name }} + value: {{ $env.value }} + {{ end }} + {{ end }} + probes: + liveness: + enabled: true + type: exec + command: + - /bin/sh + - -c + - | + getent services tftp + readiness: + enabled: true + type: exec + command: + - /bin/sh + - -c + - | + getent services tftp + startup: + enabled: true + type: exec + command: + - /bin/sh + - -c + - | + getent services tftp + initContainers: + {{- include "ix.v1.common.app.permissions" (dict "containerName" "01-permissions" + "UID" 9069 + "GID" 9069 + "mode" "check" + "chmod" (ternary "757" "555" .Values.tftpConfig.allowCreate) + "type" "init") | nindent 8 }} + + +{{/* Service */}} +service: + tftp: + enabled: true + primary: true + type: NodePort + targetSelector: tftp + ports: + tftp: + enabled: true + primary: true + port: {{ .Values.tftpNetwork.tftpPort }} + nodePort: {{ .Values.tftpNetwork.tftpPort }} + targetPort: 69 + protocol: udp + targetSelector: tftp + +{{/* Persistence */}} +persistence: + tftpboot: + enabled: true + type: {{ .Values.tftpStorage.tftpboot.type }} + datasetName: {{ .Values.tftpStorage.tftpboot.datasetName | default "" }} + hostPath: {{ .Values.tftpStorage.tftpboot.hostPath | default "" }} + targetSelector: + tftp: + tftp: + mountPath: /tftpboot + 01-permissions: + mountPath: /mnt/directories/tftpboot +{{- end -}} diff --git a/library/ix-dev/community/tftpd-hpa/templates/common.yaml b/library/ix-dev/community/tftpd-hpa/templates/common.yaml new file mode 100644 index 0000000000..ff8b07ce11 --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/templates/common.yaml @@ -0,0 +1,6 @@ +{{- include "ix.v1.common.loader.init" . -}} + +{{/* Merge the templates with Values */}} +{{- $_ := mustMergeOverwrite .Values (include "tftp.workload" $ | fromYaml) -}} + +{{- include "ix.v1.common.loader.apply" . -}} diff --git a/library/ix-dev/community/tftpd-hpa/upgrade_info.json b/library/ix-dev/community/tftpd-hpa/upgrade_info.json new file mode 100644 index 0000000000..767388094a --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/upgrade_info.json @@ -0,0 +1 @@ +{"filename": "values.yaml", "keys": ["image"]} diff --git a/library/ix-dev/community/tftpd-hpa/upgrade_strategy b/library/ix-dev/community/tftpd-hpa/upgrade_strategy new file mode 100755 index 0000000000..aef37b7f05 --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/upgrade_strategy @@ -0,0 +1,30 @@ +#!/usr/bin/python3 +import json +import re +import sys + +from catalog_update.upgrade_strategy import semantic_versioning + +RE_STABLE_VERSION = re.compile(r'[1-9]+\.[0-9]+\.[0-9]+') + + +def newer_mapping(image_tags): + key = list(image_tags.keys())[0] + tags = {t: t for t in image_tags[key] if RE_STABLE_VERSION.fullmatch(t)} + version = semantic_versioning(list(tags)) + if not version: + return {} + + return { + 'tags': {key: tags[version]}, + 'app_version': version, + } + + +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/tftpd-hpa/values.yaml b/library/ix-dev/community/tftpd-hpa/values.yaml new file mode 100644 index 0000000000..01b821b5cb --- /dev/null +++ b/library/ix-dev/community/tftpd-hpa/values.yaml @@ -0,0 +1,21 @@ +image: + repository: ixsystems/tftpd-hpa + pullPolicy: IfNotPresent + tag: '1.0.0' + +resources: + limits: + cpu: 4000m + memory: 8Gi + +tftpConfig: + allowCreate: true + additionalEnvs: [] +tftpNetwork: + hostNetwork: true + # Only used if hostNetwork is false + tftpPort: 30000 +tftpStorage: + tftpboot: + type: ixVolume + datasetName: tftpboot