fix(deploy): 在线更新备份 - 兼容 root-only 历史数据文件
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
## v1.2.2-preview.3
|
||||
|
||||
- 修复历史数据目录包含 root-only 备份文件时,在线更新无法创建数据目录 ZIP 的问题;仅备份命令以容器 root 身份读取挂载目录,业务 Backend 仍保持非 root 运行。
|
||||
|
||||
## v1.2.2-preview.2
|
||||
|
||||
- 在线更新页明确提示每次升级都会重新备份数据库,并校验镜像摘要、数据库迁移与服务健康状态。
|
||||
|
||||
@@ -301,7 +301,7 @@ func (m *Manager) createBackup(version string) (Backup, error) {
|
||||
if err != nil {
|
||||
return Backup{}, err
|
||||
}
|
||||
if err := m.compose(m.composePath(), version, m.config.StepTimeout, dataEntry, "exec", "-T", "backend", "tar", "-C", "/data", "-cf", "-", "."); err != nil {
|
||||
if err := m.compose(m.composePath(), version, m.config.StepTimeout, dataEntry, "exec", "-T", "--user", "root", "backend", "tar", "-C", "/data", "-cf", "-", "."); err != nil {
|
||||
return Backup{}, fmt.Errorf("备份数据目录:%w", err)
|
||||
}
|
||||
if err := archive.Close(); err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package hostupdate
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
@@ -11,6 +12,18 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type recordingRunner struct {
|
||||
calls [][]string
|
||||
}
|
||||
|
||||
func (r *recordingRunner) Run(_ context.Context, _ string, args, _ []string, stdout, _ io.Writer) error {
|
||||
r.calls = append(r.calls, append([]string(nil), args...))
|
||||
if stdout != nil {
|
||||
_, _ = io.WriteString(stdout, "backup-fixture")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestSetEnvValuePreservesOtherSettings(t *testing.T) {
|
||||
directory := t.TempDir()
|
||||
path := filepath.Join(directory, ".env")
|
||||
@@ -90,3 +103,29 @@ func TestCurrentVersionRejectsLatest(t *testing.T) {
|
||||
t.Fatal("latest tag was accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateBackupReadsBackendDataAsRoot(t *testing.T) {
|
||||
installDir := t.TempDir()
|
||||
backupDir := filepath.Join(installDir, "backups")
|
||||
if err := os.MkdirAll(backupDir, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(installDir, ".env"), []byte("POSTGRES_USER=canvas\nPOSTGRES_DB=canvas\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
runner := &recordingRunner{}
|
||||
manager := &Manager{
|
||||
config: Config{InstallDir: installDir, ComposeFile: "docker-compose.deploy.yml", EnvFile: ".env", BackupDir: backupDir},
|
||||
runner: runner,
|
||||
}
|
||||
if _, err := manager.createBackup("v1.2.2-preview.2"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, call := range runner.calls {
|
||||
joined := strings.Join(call, " ")
|
||||
if strings.Contains(joined, "exec -T --user root backend tar -C /data -cf - .") {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatalf("backend data backup did not use root: %#v", runner.calls)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user