mirror of
https://github.com/kopia/kopia.git
synced 2026-01-04 12:37:52 -05:00
221 lines
6.7 KiB
Go
221 lines
6.7 KiB
Go
package server_test
|
|
|
|
import (
|
|
"context"
|
|
"math"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/kopia/kopia/internal/apiclient"
|
|
"github.com/kopia/kopia/internal/mockfs"
|
|
"github.com/kopia/kopia/internal/repotesting"
|
|
"github.com/kopia/kopia/internal/serverapi"
|
|
"github.com/kopia/kopia/internal/servertesting"
|
|
"github.com/kopia/kopia/internal/testutil"
|
|
"github.com/kopia/kopia/internal/uitask"
|
|
"github.com/kopia/kopia/repo"
|
|
"github.com/kopia/kopia/repo/manifest"
|
|
"github.com/kopia/kopia/snapshot"
|
|
"github.com/kopia/kopia/snapshot/restore"
|
|
"github.com/kopia/kopia/snapshot/upload"
|
|
)
|
|
|
|
func TestRestoreSnapshots(t *testing.T) {
|
|
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
|
|
|
si1 := env.LocalPathSourceInfo("/dummy/path")
|
|
|
|
var id11 manifest.ID
|
|
|
|
require.NoError(t, repo.WriteSession(ctx, env.Repository, repo.WriteSessionOptions{Purpose: "Test"}, func(ctx context.Context, w repo.RepositoryWriter) error {
|
|
u := upload.NewUploader(w)
|
|
|
|
dir1 := mockfs.NewDirectory()
|
|
|
|
dir1.AddFile("file1", []byte{1, 2, 3}, 0o644)
|
|
dir1.AddDir("dir1", 0o644).AddFile("file2", []byte{1, 2, 4}, 0o644)
|
|
|
|
man11, err := u.Upload(ctx, dir1, nil, si1)
|
|
require.NoError(t, err)
|
|
id11, err = snapshot.SaveSnapshot(ctx, w, man11)
|
|
require.NoError(t, err)
|
|
|
|
return nil
|
|
}))
|
|
|
|
srvInfo := servertesting.StartServer(t, env, false)
|
|
|
|
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
|
BaseURL: srvInfo.BaseURL,
|
|
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
|
Username: servertesting.TestUIUsername,
|
|
Password: servertesting.TestUIPassword,
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.NoError(t, cli.FetchCSRFTokenForTesting(ctx))
|
|
|
|
t.Run("Filesystem", func(t *testing.T) {
|
|
targetPath1 := testutil.TempDirectory(t)
|
|
restoreTask1, err := serverapi.Restore(ctx, cli, &serverapi.RestoreRequest{
|
|
Root: string(id11),
|
|
Options: restore.Options{
|
|
RestoreDirEntryAtDepth: math.MaxInt32,
|
|
},
|
|
Filesystem: &restore.FilesystemOutput{
|
|
TargetPath: targetPath1,
|
|
SkipOwners: true,
|
|
SkipPermissions: true,
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
waitForTask(t, cli, restoreTask1.TaskID, 30*time.Second)
|
|
require.FileExists(t, filepath.Join(targetPath1, "file1"))
|
|
require.FileExists(t, filepath.Join(targetPath1, "dir1", "file2"))
|
|
})
|
|
|
|
t.Run("FilesystemSubdir", func(t *testing.T) {
|
|
targetPath1 := testutil.TempDirectory(t)
|
|
restoreTask1, err := serverapi.Restore(ctx, cli, &serverapi.RestoreRequest{
|
|
Root: string(id11) + "/dir1",
|
|
Options: restore.Options{
|
|
RestoreDirEntryAtDepth: math.MaxInt32,
|
|
},
|
|
Filesystem: &restore.FilesystemOutput{
|
|
TargetPath: targetPath1,
|
|
SkipOwners: true,
|
|
SkipPermissions: true,
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, uitask.StatusSuccess, waitForTask(t, cli, restoreTask1.TaskID, 30*time.Second).Status)
|
|
|
|
require.FileExists(t, filepath.Join(targetPath1, "file2"))
|
|
})
|
|
|
|
t.Run("FilesystemFullShallowRestore", func(t *testing.T) {
|
|
targetPath1 := testutil.TempDirectory(t)
|
|
restoreTask1, err := serverapi.Restore(ctx, cli, &serverapi.RestoreRequest{
|
|
Root: string(id11),
|
|
Options: restore.Options{},
|
|
Filesystem: &restore.FilesystemOutput{
|
|
TargetPath: targetPath1,
|
|
SkipOwners: true,
|
|
SkipPermissions: true,
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, uitask.StatusSuccess, waitForTask(t, cli, restoreTask1.TaskID, 30*time.Second).Status)
|
|
require.FileExists(t, filepath.Join(targetPath1, "file1.kopia-entry"))
|
|
require.DirExists(t, filepath.Join(targetPath1, "dir1.kopia-entry"))
|
|
require.FileExists(t, filepath.Join(targetPath1, "dir1.kopia-entry", ".kopia-entry"))
|
|
})
|
|
|
|
t.Run("FilesystemPartialShallowRestore", func(t *testing.T) {
|
|
targetPath1 := testutil.TempDirectory(t)
|
|
restoreTask1, err := serverapi.Restore(ctx, cli, &serverapi.RestoreRequest{
|
|
Root: string(id11),
|
|
Options: restore.Options{
|
|
RestoreDirEntryAtDepth: 1,
|
|
},
|
|
Filesystem: &restore.FilesystemOutput{
|
|
TargetPath: targetPath1,
|
|
SkipOwners: true,
|
|
SkipPermissions: true,
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, uitask.StatusSuccess, waitForTask(t, cli, restoreTask1.TaskID, 30*time.Second).Status)
|
|
require.FileExists(t, filepath.Join(targetPath1, "file1"))
|
|
require.DirExists(t, filepath.Join(targetPath1, "dir1"))
|
|
require.FileExists(t, filepath.Join(targetPath1, "dir1", "file2.kopia-entry"))
|
|
})
|
|
|
|
t.Run("ZipFile", func(t *testing.T) {
|
|
outputZipFile := filepath.Join(testutil.TempDirectory(t), "test1.zip")
|
|
restoreTask1, err := serverapi.Restore(ctx, cli, &serverapi.RestoreRequest{
|
|
Root: string(id11),
|
|
Options: restore.Options{
|
|
RestoreDirEntryAtDepth: math.MaxInt32,
|
|
},
|
|
ZipFile: outputZipFile,
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, uitask.StatusSuccess, waitForTask(t, cli, restoreTask1.TaskID, 30*time.Second).Status)
|
|
require.FileExists(t, outputZipFile)
|
|
})
|
|
|
|
t.Run("UncompressedZipFile", func(t *testing.T) {
|
|
outputZipFile := filepath.Join(testutil.TempDirectory(t), "test1.zip")
|
|
restoreTask1, err := serverapi.Restore(ctx, cli, &serverapi.RestoreRequest{
|
|
Root: string(id11),
|
|
Options: restore.Options{
|
|
RestoreDirEntryAtDepth: math.MaxInt32,
|
|
},
|
|
ZipFile: outputZipFile,
|
|
UncompressedZip: true,
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, uitask.StatusSuccess, waitForTask(t, cli, restoreTask1.TaskID, 30*time.Second).Status)
|
|
require.FileExists(t, outputZipFile)
|
|
})
|
|
|
|
t.Run("TarFile", func(t *testing.T) {
|
|
outputTarFile := filepath.Join(testutil.TempDirectory(t), "test1.tar")
|
|
restoreTask1, err := serverapi.Restore(ctx, cli, &serverapi.RestoreRequest{
|
|
Root: string(id11),
|
|
Options: restore.Options{
|
|
RestoreDirEntryAtDepth: math.MaxInt32,
|
|
},
|
|
TarFile: outputTarFile,
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, uitask.StatusSuccess, waitForTask(t, cli, restoreTask1.TaskID, 30*time.Second).Status)
|
|
require.FileExists(t, outputTarFile)
|
|
})
|
|
|
|
t.Run("InvalidRequest", func(t *testing.T) {
|
|
requests := []*serverapi.RestoreRequest{
|
|
{
|
|
Root: string(id11),
|
|
// no output
|
|
},
|
|
{
|
|
// no root
|
|
ZipFile: filepath.Join(testutil.TempDirectory(t), "test1.zip"),
|
|
},
|
|
{
|
|
Root: string(id11 + "bad"),
|
|
ZipFile: filepath.Join(testutil.TempDirectory(t), "test1.zip"),
|
|
},
|
|
{
|
|
Root: string(id11),
|
|
ZipFile: "/no/such/directory/" + uuid.NewString() + "/test1.zip",
|
|
},
|
|
{
|
|
Root: string(id11),
|
|
TarFile: "/no/such/directory/" + uuid.NewString() + "/test1.tar",
|
|
},
|
|
}
|
|
|
|
for _, req := range requests {
|
|
_, err := serverapi.Restore(ctx, cli, req)
|
|
|
|
var se apiclient.HTTPStatusError
|
|
|
|
require.ErrorAs(t, err, &se)
|
|
}
|
|
})
|
|
}
|