v0.57.0: stable host-storage list + per-app Tier-2 config panel
Part A of the UI-fixes/storage-spike spec.
A1: enrichHostStorageTargets sorts /api/host-metrics storage_targets
server-side and attaches friendly Hungarian labels + purpose, fixing the
#host-storage-bars reorder-on-poll bug. Display labels only — PVE storage
ids are never renamed.
A2: new GET/POST /stacks/{name}/backup Tier-2 config panel; the "2. mentés"
Beállítás button is repointed there from the dead-end deploy page. Customer
can pin a target drive or disable Tier 2; preference is preserved across the
runner's status writes. Always visible (single-SSD + non-HDD apps included).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,12 @@ type CrossDriveBackup struct {
|
||||
LastError string `json:"last_error,omitempty"`
|
||||
LastDuration string `json:"last_duration,omitempty"` // "2m34s"
|
||||
LastSizeHuman string `json:"last_size_human,omitempty"` // "1.2 GB"
|
||||
|
||||
// Customer preference (set from the per-app Tier-2 config panel; PRESERVED across the runner's
|
||||
// status writes). UserDisabled turns Tier 2 off for this app; PreferredTarget pins a chosen
|
||||
// destination drive (a registered storage Path) instead of the auto-pick ("" = auto).
|
||||
UserDisabled bool `json:"user_disabled,omitempty"`
|
||||
PreferredTarget string `json:"preferred_target,omitempty"`
|
||||
}
|
||||
|
||||
// StoragePath represents a registered external storage location.
|
||||
@@ -388,6 +394,26 @@ func (s *Settings) UpdateCrossDriveStatus(stackName string, fn func(*CrossDriveB
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// SetTier2Preference records the customer's Tier-2 choice (from the per-app config panel) WITHOUT
|
||||
// disturbing the runner's status fields: it merges into the existing config if one is present, else
|
||||
// seeds a minimal config carrying just the preference. The Tier-2 runner reads UserDisabled (skip)
|
||||
// and PreferredTarget (pin a destination) and preserves both on every status write.
|
||||
func (s *Settings) SetTier2Preference(stackName string, disabled bool, preferredTarget string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.AppBackup == nil {
|
||||
s.AppBackup = make(map[string]AppBackupPrefs)
|
||||
}
|
||||
existing := s.AppBackup[stackName]
|
||||
if existing.CrossDrive == nil {
|
||||
existing.CrossDrive = &CrossDriveBackup{Method: "rsync", Schedule: "daily"}
|
||||
}
|
||||
existing.CrossDrive.UserDisabled = disabled
|
||||
existing.CrossDrive.PreferredTarget = preferredTarget
|
||||
s.AppBackup[stackName] = existing
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// GetAllCrossDriveConfigs returns all apps with a cross-drive config (enabled or not).
|
||||
func (s *Settings) GetAllCrossDriveConfigs() map[string]*CrossDriveBackup {
|
||||
s.mu.RLock()
|
||||
|
||||
Reference in New Issue
Block a user