fix: storage:list reads from attachments, deprecate storage-list trigger

storage:list was calling the storage-list plugn trigger which read -v lines from docker-options. After the install-time migration drains those lines into the attachment store, that source is empty for every migrated app and for any app that only ever used storage:create + storage:mount. The fix moves CommandList to call a new in-process ListAppMountEntries helper that reads attachments directly, surfaces the entry name in JSON output via a new entry_name field, and falls back to the entry name as the host token for k3s entries with no host path so the colon form remains well-formed. The storage-list plugn trigger is kept for back-compat with external callers but emits a deprecation warning and now reads from the same attachment-driven source.
This commit is contained in:
Jose Diaz-Gonzalez
2026-04-29 22:51:50 -04:00
parent 6a5d568944
commit d75228f165
6 changed files with 258 additions and 59 deletions

View File

@@ -1,6 +1,7 @@
package storage
import (
"encoding/json"
"errors"
"fmt"
"os"
@@ -226,7 +227,9 @@ func CommandUnmount(input CommandUnmountInput) error {
return RemoveAttachment(input.AppName, input.NameOrPath, input.ContainerDir)
}
// CommandList lists all bind mounts for an app
// CommandList lists all bind mounts for an app. Reads attachments
// directly from the storage plugin's own state rather than going through
// the deprecated `storage-list` plugn trigger.
func CommandList(appName string, format string) error {
if err := common.VerifyAppName(appName); err != nil {
return err
@@ -236,34 +239,29 @@ func CommandList(appName string, format string) error {
return errors.New("Invalid --format value specified")
}
if format == "text" {
common.LogInfo1Quiet(fmt.Sprintf("%s volume bind-mounts:", appName))
}
results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
Trigger: "storage-list",
Args: []string{appName, "deploy", format},
})
rows, err := ListAppMountEntries(appName, PhaseDeploy)
if err != nil {
return err
}
output := results.StdoutContents()
if format == "text" && output != "" {
lines := strings.Split(strings.TrimSpace(output), "\n")
for _, line := range lines {
if line != "" {
if os.Getenv("DOKKU_QUIET_OUTPUT") != "" {
fmt.Println(line)
} else {
common.LogVerbose(line)
}
}
if format == "json" {
output, err := json.Marshal(rows)
if err != nil {
return err
}
} else if output != "" {
fmt.Println(output)
fmt.Println(string(output))
return nil
}
common.LogInfo1Quiet(fmt.Sprintf("%s volume bind-mounts:", appName))
for _, row := range rows {
line := formatStorageListEntry(row)
if os.Getenv("DOKKU_QUIET_OUTPUT") != "" {
fmt.Println(line)
} else {
common.LogVerbose(line)
}
}
return nil
}