feat: expose per-attachment fields in storage:report

storage:report gains a flat dotted key per attachment field (entry-name, host-path, container-path, phases, process-type, subpath, readonly, volume-options, volume-chown) under the --storage-attachment.<index>.<field> shape. Both stdout and JSON pick the keys up through the existing common.ReportSingleApp pipeline. Attachments that reference a missing storage entry emit a warning and are skipped, so the rest of the report still renders. Closes #8710.
This commit is contained in:
Jose Diaz-Gonzalez
2026-05-30 04:11:30 -04:00
parent 3bb21b6987
commit bec6b9f14a
3 changed files with 256 additions and 9 deletions

View File

@@ -1,6 +1,12 @@
package storage
import "github.com/dokku/dokku/plugins/common"
import (
"fmt"
"strconv"
"strings"
"github.com/dokku/dokku/plugins/common"
)
func ReportSingleApp(appName string, format string, infoFlag string) error {
if appName != "--global" {
@@ -9,14 +15,26 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
}
}
var flags map[string]common.ReportFunc
if appName == "--global" {
flags = map[string]common.ReportFunc{}
} else {
flags = map[string]common.ReportFunc{
"--storage-build-mounts": reportBuildMounts,
"--storage-deploy-mounts": reportDeployMounts,
"--storage-run-mounts": reportRunMounts,
flags := map[string]common.ReportFunc{}
if appName != "--global" {
flags["--storage-build-mounts"] = reportBuildMounts
flags["--storage-deploy-mounts"] = reportDeployMounts
flags["--storage-run-mounts"] = reportRunMounts
attachments, err := LoadAttachments(appName)
if err != nil {
common.LogWarn(fmt.Sprintf("Unable to load storage attachments for %q: %s", appName, err))
attachments = nil
}
index := 0
for _, attachment := range attachments {
entry, err := LoadEntry(attachment.EntryName)
if err != nil {
common.LogWarn(fmt.Sprintf("Skipping attachment on %q: missing entry %q (%s)", appName, attachment.EntryName, err))
continue
}
index++
registerAttachmentFlags(flags, index, attachment, entry)
}
}
@@ -50,3 +68,25 @@ func reportDeployMounts(appName string) string {
func reportRunMounts(appName string) string {
return GetBindMountsForDisplay(appName, "run")
}
// registerAttachmentFlags adds one report flag per Attachment field for the
// given 1-based index. Host path is resolved from the referenced Entry
// (falling back to entry.Name when the entry has no host path, matching
// ListAppMountEntries).
func registerAttachmentFlags(flags map[string]common.ReportFunc, index int, att *Attachment, entry *Entry) {
prefix := fmt.Sprintf("--storage-attachment.%d.", index)
captured := att
host := entry.HostPath
if host == "" {
host = entry.Name
}
flags[prefix+"entry-name"] = func(string) string { return captured.EntryName }
flags[prefix+"host-path"] = func(string) string { return host }
flags[prefix+"container-path"] = func(string) string { return captured.ContainerPath }
flags[prefix+"phases"] = func(string) string { return strings.Join(captured.Phases, ",") }
flags[prefix+"process-type"] = func(string) string { return captured.ProcessType }
flags[prefix+"subpath"] = func(string) string { return captured.Subpath }
flags[prefix+"readonly"] = func(string) string { return strconv.FormatBool(captured.Readonly) }
flags[prefix+"volume-options"] = func(string) string { return captured.VolumeOptions }
flags[prefix+"volume-chown"] = func(string) string { return captured.VolumeChown }
}