From 6a10ddad606e838a634016b23e37fb48838fb292 Mon Sep 17 00:00:00 2001 From: Olli Hauer Date: Fri, 3 Jul 2026 08:06:10 +0200 Subject: [PATCH 1/2] feat: add trident-nfs-tools extension for NFS support on Talos Trident's chwrap mechanism shells out to mkdir to create NFS mountpoint directories. Talos Linux does not ship mkdir, causing NFS mounts to fail with exit status 32. This extension provides /usr/local/sbin/mkdir (busybox) on the host, enabling Trident NFS volumes to work on Talos. Upstream fix: https://github.com/NetApp/trident/pull/1152 Related: https://github.com/NetApp/trident/issues/806 Signed-off-by: Oliver Hauer --- Makefile | 1 + storage/trident-nfs-tools/README.md | 42 ++++++++++++++++++++ storage/trident-nfs-tools/manifest.yaml.tmpl | 17 ++++++++ storage/trident-nfs-tools/pkg.yaml | 27 +++++++++++++ storage/trident-nfs-tools/vars.yaml | 3 ++ 5 files changed, 90 insertions(+) create mode 100644 storage/trident-nfs-tools/README.md create mode 100644 storage/trident-nfs-tools/manifest.yaml.tmpl create mode 100644 storage/trident-nfs-tools/pkg.yaml create mode 100644 storage/trident-nfs-tools/vars.yaml diff --git a/Makefile b/Makefile index 56fad7e8..385f4785 100644 --- a/Makefile +++ b/Makefile @@ -131,6 +131,7 @@ TARGETS += tailscale TARGETS += tenstorrent TARGETS += thunderbolt TARGETS += trident-iscsi-tools +TARGETS += trident-nfs-tools TARGETS += uhid TARGETS += uinput TARGETS += usb-modem-drivers diff --git a/storage/trident-nfs-tools/README.md b/storage/trident-nfs-tools/README.md new file mode 100644 index 00000000..ab7dad92 --- /dev/null +++ b/storage/trident-nfs-tools/README.md @@ -0,0 +1,42 @@ +# trident-nfs-tools + +This extension provides `mkdir` on the host for **NetApp Trident CSI** NFS volume support on Talos Linux. + +## Problem + +Trident's `chwrap` mechanism shells out to `mkdir` to create NFS mountpoint directories. +Talos Linux does not ship `mkdir` or any coreutils, causing NFS mounts to fail with: + +``` +Mkdir failed: exit status 2 +error mounting NFS volume ... exit status 32 +``` + +Note: The iSCSI code path in Trident uses Go's native `os.MkdirAll()` and does not +have this problem. Only the NFS code path shells out to the `mkdir` binary. + +## What's Included + +* **mkdir** — busybox multi-call binary (only depends on musl libc) + +## Use Case + +To run [trident-operator](https://github.com/NetApp/trident) with NFS, you need this extension +in addition to `nfs-utils` (for NFSv3 locking support): + +```yaml +systemExtensions: + - siderolabs/nfs-utils + - siderolabs/trident-nfs-tools +``` + +## Upstream Fix + +PR [#1152](https://github.com/NetApp/trident/pull/1152) replaces the `mkdir` shell-out +with Go's native `os.MkdirAll()`. Once merged and released, this extension will no longer +be needed. + +## References + +- [Trident issue #806](https://github.com/NetApp/trident/issues/806) +- [Trident PR #1152](https://github.com/NetApp/trident/pull/1152) diff --git a/storage/trident-nfs-tools/manifest.yaml.tmpl b/storage/trident-nfs-tools/manifest.yaml.tmpl new file mode 100644 index 00000000..a03f8bbd --- /dev/null +++ b/storage/trident-nfs-tools/manifest.yaml.tmpl @@ -0,0 +1,17 @@ +version: v1alpha1 +metadata: + name: trident-nfs-tools + version: "{{ .VERSION }}" + author: Oliver Hauer + description: | + [{{ .TIER }}] This system extension provides mkdir on the host for NetApp Trident CSI + NFS volume support on Talos Linux. + + Trident's chwrap mechanism requires mkdir to be present on the host filesystem. + Without it, NFS mounts fail with "exit status 32". + + See: https://github.com/NetApp/trident/issues/806 + See: https://github.com/NetApp/trident/pull/1152 + compatibility: + talos: + version: ">= v1.13.0" diff --git a/storage/trident-nfs-tools/pkg.yaml b/storage/trident-nfs-tools/pkg.yaml new file mode 100644 index 00000000..a4f9e9b2 --- /dev/null +++ b/storage/trident-nfs-tools/pkg.yaml @@ -0,0 +1,27 @@ +name: trident-nfs-tools +variant: scratch +shell: /bin/bash +dependencies: + - stage: base +steps: + - install: + - | + mkdir -p /rootfs/usr/local/sbin + + # Use busybox mkdir from the build tools image. + # busybox is a multi-call binary; when invoked as "mkdir" (argv[0]) + # it acts as mkdir. Only depends on musl libc which is on Talos. + cp /usr/bin/busybox /rootfs/usr/local/sbin/mkdir + - | + sed -i "s#\$VERSION#{{ .VERSION }}#" /pkg/manifest.yaml + - test: + - | + mkdir -p /extensions-validator-rootfs + cp -r /rootfs/ /extensions-validator-rootfs/rootfs + cp /pkg/manifest.yaml /extensions-validator-rootfs/manifest.yaml + /extensions-validator validate --rootfs=/extensions-validator-rootfs --pkg-name="${PKG_NAME}" +finalize: + - from: /rootfs + to: /rootfs + - from: /pkg/manifest.yaml + to: / diff --git a/storage/trident-nfs-tools/vars.yaml b/storage/trident-nfs-tools/vars.yaml new file mode 100644 index 00000000..8daac951 --- /dev/null +++ b/storage/trident-nfs-tools/vars.yaml @@ -0,0 +1,3 @@ +VERSION: v0.1.0 + +TIER: "contrib" From 800608f88f35b49ea83834876a64787e41a15c72 Mon Sep 17 00:00:00 2001 From: Albert <33936483+Orzelius@users.noreply.github.com> Date: Mon, 6 Jul 2026 18:45:52 +0900 Subject: [PATCH 2/2] docs: document how to build a single extensions and a catalog (#1127) add docs about local dev as well Signed-off-by: Orzelius <33936483+Orzelius@users.noreply.github.com> --- .conform.yaml | 4 ++-- .github/workflows/ci.yaml | 23 +++++++++--------- .github/workflows/grype-scan-cron.yaml | 8 +++---- .github/workflows/lock.yml | 4 ++-- .../workflows/slack-notify-ci-failure.yaml | 7 +++--- .github/workflows/slack-notify.yaml | 4 ++-- .github/workflows/stale.yml | 14 +++++++---- .github/workflows/weekly.yaml | 8 +++---- .kres.yaml | 2 +- Makefile | 6 ++--- README.md | 24 +++++++++++++++++++ lefthook.yml | 6 +++-- 12 files changed, 71 insertions(+), 39 deletions(-) diff --git a/.conform.yaml b/.conform.yaml index 36a6c331..7fd2e392 100644 --- a/.conform.yaml +++ b/.conform.yaml @@ -1,6 +1,6 @@ -# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2025-11-13T15:52:54Z by kres e1d6dac. +# Generated on 2026-06-21T11:28:45Z by kres a07fce6. policies: - type: commit diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1977b964..cc1a1b1f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,11 +1,11 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-05-28T17:01:21Z by kres e1a258d. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true -"on": +'on': push: branches: - main @@ -27,7 +27,8 @@ jobs: pull-requests: read runs-on: group: pkgs - if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/')) + if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, + 'dependabot/')) outputs: labels: ${{ steps.retrieve-pr-labels.outputs.result }} steps: @@ -57,13 +58,13 @@ jobs: done continue-on-error: true - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # version: v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # version: v7.0.0 - name: Unshallow run: | git fetch --prune --unshallow - name: Set up Docker Buildx id: setup-buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # version: v4.1.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # version: v4.2.0 with: append: | - endpoint: tcp://buildkit-arm64.ci.svc.cluster.local:1234 @@ -80,7 +81,7 @@ jobs: make nonfree - name: Login to registry if: github.event_name != 'pull_request' - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # version: v4.2.0 + uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # version: v4.4.0 with: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io @@ -135,7 +136,7 @@ jobs: make release-notes - name: Release if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # version: v3.0.0 + uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # version: v3.0.1 with: body_path: _out/RELEASE_NOTES.md draft: "true" @@ -172,13 +173,13 @@ jobs: done continue-on-error: true - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # version: v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # version: v7.0.0 - name: Unshallow run: | git fetch --prune --unshallow - name: Set up Docker Buildx id: setup-buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # version: v4.1.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # version: v4.2.0 with: driver: remote endpoint: tcp://buildkit-amd64.ci.svc.cluster.local:1234 @@ -226,13 +227,13 @@ jobs: done continue-on-error: true - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # version: v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # version: v7.0.0 - name: Unshallow run: | git fetch --prune --unshallow - name: Set up Docker Buildx id: setup-buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # version: v4.1.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # version: v4.2.0 with: append: | - endpoint: tcp://buildkit-arm64.ci.svc.cluster.local:1234 diff --git a/.github/workflows/grype-scan-cron.yaml b/.github/workflows/grype-scan-cron.yaml index 218180a3..85c26512 100644 --- a/.github/workflows/grype-scan-cron.yaml +++ b/.github/workflows/grype-scan-cron.yaml @@ -1,11 +1,11 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-05-28T17:01:21Z by kres e1a258d. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true -"on": +'on': schedule: - cron: 30 7 * * * name: grype-scan-cron @@ -40,13 +40,13 @@ jobs: done continue-on-error: true - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # version: v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # version: v7.0.0 - name: Unshallow run: | git fetch --prune --unshallow - name: Set up Docker Buildx id: setup-buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # version: v4.1.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # version: v4.2.0 with: driver: remote endpoint: tcp://buildkit-amd64.ci.svc.cluster.local:1234 diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 6ed93b76..33cb0447 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -1,8 +1,8 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-05-28T17:01:21Z by kres e1a258d. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. -"on": +'on': schedule: - cron: 0 2 * * * name: Lock old issues diff --git a/.github/workflows/slack-notify-ci-failure.yaml b/.github/workflows/slack-notify-ci-failure.yaml index ecfcafc9..c2956017 100644 --- a/.github/workflows/slack-notify-ci-failure.yaml +++ b/.github/workflows/slack-notify-ci-failure.yaml @@ -1,8 +1,8 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-05-21T11:52:49Z by kres 44d3d02. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. -"on": +'on': workflow_run: workflows: - default @@ -17,7 +17,8 @@ jobs: slack-notify: runs-on: group: generic - if: github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event != 'pull_request' + if: github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event + != 'pull_request' steps: - name: Slack Notify uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # version: v3.0.3 diff --git a/.github/workflows/slack-notify.yaml b/.github/workflows/slack-notify.yaml index e190d6f4..9f6ac1a5 100644 --- a/.github/workflows/slack-notify.yaml +++ b/.github/workflows/slack-notify.yaml @@ -1,8 +1,8 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-05-21T11:52:49Z by kres 44d3d02. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. -"on": +'on': workflow_run: workflows: - default diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3de9a815..b8889dc8 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,8 +1,8 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-05-28T17:01:21Z by kres e1a258d. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. -"on": +'on': schedule: - cron: 30 1 * * * name: Close stale issues and PRs @@ -17,11 +17,15 @@ jobs: - name: Close stale issues and PRs uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # version: v10.3.0 with: - close-issue-message: This issue was closed because it has been stalled for 7 days with no activity. + close-issue-message: This issue was closed because it has been stalled for + 7 days with no activity. days-before-issue-close: "5" days-before-issue-stale: "180" days-before-pr-close: "-1" days-before-pr-stale: "45" operations-per-run: "2000" - stale-issue-message: This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days. - stale-pr-message: This PR is stale because it has been open 45 days with no activity. + stale-issue-message: This issue is stale because it has been open 180 days + with no activity. Remove stale label or comment or this will be closed + in 7 days. + stale-pr-message: This PR is stale because it has been open 45 days with + no activity. diff --git a/.github/workflows/weekly.yaml b/.github/workflows/weekly.yaml index 0fc41af4..15bebe62 100644 --- a/.github/workflows/weekly.yaml +++ b/.github/workflows/weekly.yaml @@ -1,11 +1,11 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-05-28T17:01:21Z by kres e1a258d. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true -"on": +'on': schedule: - cron: 30 1 * * 1 name: weekly @@ -40,13 +40,13 @@ jobs: done continue-on-error: true - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # version: v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # version: v7.0.0 - name: Unshallow run: | git fetch --prune --unshallow - name: Set up Docker Buildx id: setup-buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # version: v4.1.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # version: v4.2.0 with: append: | - endpoint: tcp://buildkit-arm64.ci.svc.cluster.local:1234 diff --git a/.kres.yaml b/.kres.yaml index 31af6904..db8a7cbd 100644 --- a/.kres.yaml +++ b/.kres.yaml @@ -227,7 +227,7 @@ spec: script: - | @echo "Generating image descriptions..." - @echo -n "" > internal/extensions/descriptions.yaml + @printf '' > internal/extensions/descriptions.yaml @for image in $(shell cat internal/extensions/image-digests); do \ crane export $$image - | tar x -O --occurrence=1 manifest.yaml | yq -r ". += {\"$$image\": {\"author\": .metadata.author, \"description\": .metadata.description}} | del(.metadata, .version)" - >> internal/extensions/descriptions.yaml; \ done diff --git a/Makefile b/Makefile index 385f4785..37fd638b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-07-01T13:21:36Z by kres 7421bcd. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. # common variables @@ -27,7 +27,7 @@ SOURCE_DATE_EPOCH := $(shell git log $(INITIAL_COMMIT_SHA) --pretty=%ct) # sync bldr image with pkgfile -BLDR_RELEASE := v0.6.0 +BLDR_RELEASE := v0.6.1 BLDR_IMAGE := ghcr.io/siderolabs/bldr:$(BLDR_RELEASE) BLDR := docker run --rm --user $(shell id -u):$(shell id -g) --volume $(PWD):/src --entrypoint=/bldr $(BLDR_IMAGE) --root=/src @@ -286,7 +286,7 @@ internal/extensions/image-digests: $(ARTIFACTS)/bldr .PHONY: internal/extensions/descriptions.yaml internal/extensions/descriptions.yaml: internal/extensions/image-digests @echo "Generating image descriptions..." - @echo -n "" > internal/extensions/descriptions.yaml + @printf '' > internal/extensions/descriptions.yaml @for image in $(shell cat internal/extensions/image-digests); do \ crane export $$image - | tar x -O --occurrence=1 manifest.yaml | yq -r ". += {\"$$image\": {\"author\": .metadata.author, \"description\": .metadata.description}} | del(.metadata, .version)" - >> internal/extensions/descriptions.yaml; \ done diff --git a/README.md b/README.md index 131b89bf..8f4ac500 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,30 @@ The rough flow should look like the following: - You can now build your extension using make like `make PLATFORM=linux/amd64` - If you wish to output the contents of the image and validate your install, you can issue `make local- PLATFORM=linux/amd64 DEST=_out`. The contents will then be present in the `_out` directory. +### Local testing and development + +> **macOS:** some targets (e.g. `descriptions.yaml`) need GNU tar. + +To build and push an extension to a local registry use: + +```bash +make PUSH=true REGISTRY=127.0.0.1:5005 USERNAME= PUSH=true +``` + +Instructions on how to set up the builder can be found [here](https://docs.siderolabs.com/talos/latest/build-and-extend-talos/custom-images-and-development/developing-talos#prepare) + +#### Building the Extensions Catalog Locally + +The `extensions` target builds the catalog image (the `image-digests` and `descriptions.yaml` of all `TARGETS`). + +You can build the catalog scoping it with `TARGETS`/`NONFREE_TARGETS` with: + +```bash +make extensions PUSH=true REGISTRY=host.docker.internal:5005 USERNAME= \ + TARGETS="" NONFREE_TARGETS= PUSH=true TAG= +``` + + ### Creating `manifest.yaml` The `manifest.yaml` file should match the following format: diff --git a/lefthook.yml b/lefthook.yml index 2f3fc003..f56954e4 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -1,9 +1,11 @@ # THIS FILE WAS AUTOMATICALLY GENERATED BY KRES, PLEASE DO NOT EDIT. # -# Generated on 2026-06-03T06:40:21Z by kres d4e4c90. +# Generated on 2026-07-06T09:25:33Z by kres 14a38a3. -commit-msg: +post-commit: parallel: false commands: conformance: run: make conformance + env: + USERNAME: siderolabs