Backupwriter skeleton code (#141)

Add skeleton and test for backing up data with kopia

Full code for launching kopia snapshots is present but code for building
the directory structure to hand kopia is not. Therefore, no data will be
backed up right now.
This commit is contained in:
ashmrtn 2022-06-06 15:59:21 -07:00 committed by GitHub
parent d5d92e707d
commit f84d8e34d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 104 additions and 5 deletions

View File

@ -3,21 +3,32 @@ package kopia
import (
"context"
"github.com/kopia/kopia/fs"
"github.com/kopia/kopia/fs/virtualfs"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/repo/blob"
"github.com/kopia/kopia/snapshot"
"github.com/kopia/kopia/snapshot/policy"
"github.com/kopia/kopia/snapshot/snapshotfs"
"github.com/pkg/errors"
"github.com/alcionai/corso/internal/connector"
"github.com/alcionai/corso/pkg/storage"
)
const (
defaultKopiaConfigFilePath = "/tmp/repository.config"
// TODO(ashmrtnz): These should be some values from upper layer corso,
// possibly corresponding to who is making the backup.
kTestHost = "a-test-machine"
kTestUser = "testUser"
)
var (
errInit = errors.New("initializing repo")
errConnect = errors.New("connecting repo")
errInit = errors.New("initializing repo")
errConnect = errors.New("connecting repo")
errNotConnected = errors.New("not connected to repo")
)
type BackupStats struct {
@ -35,7 +46,7 @@ func manifestToStats(man *snapshot.Manifest) BackupStats {
TotalDirectoryCount: int(man.Stats.TotalDirectoryCount),
IgnoredErrorCount: int(man.Stats.IgnoredErrorCount),
ErrorCount: int(man.Stats.ErrorCount),
Incomplete: man.IncompleteReason == "",
Incomplete: man.IncompleteReason != "",
IncompleteReason: man.IncompleteReason,
}
}
@ -148,3 +159,68 @@ func (kw *KopiaWrapper) open(ctx context.Context, password string) error {
kw.rep = rep
return nil
}
func inflateDirTree(ctx context.Context, collections []connector.DataCollection) (fs.Directory, error) {
// TODO(ashmrtnz): Implement when virtualfs.StreamingDirectory is available.
return virtualfs.NewStaticDirectory("sample-dir", []fs.Entry{}), nil
}
func (kw KopiaWrapper) BackupCollections(
ctx context.Context,
collections []connector.DataCollection,
) (*BackupStats, error) {
if kw.rep == nil {
return nil, errNotConnected
}
dirTree, err := inflateDirTree(ctx, collections)
if err != nil {
return nil, errors.Wrap(err, "building kopia directories")
}
stats, err := kw.makeSnapshotWithRoot(ctx, dirTree)
if err != nil {
return nil, err
}
return stats, nil
}
func (kw KopiaWrapper) makeSnapshotWithRoot(
ctx context.Context,
root fs.Directory,
) (*BackupStats, error) {
si := snapshot.SourceInfo{
Host: kTestHost,
UserName: kTestUser,
// TODO(ashmrtnz): will this be something useful for snapshot lookups later?
Path: root.Name(),
}
ctx, rw, err := kw.rep.NewWriter(ctx, repo.WriteSessionOptions{})
if err != nil {
return nil, errors.Wrap(err, "get repo writer")
}
policyTree, err := policy.TreeForSource(ctx, kw.rep, si)
if err != nil {
return nil, errors.Wrap(err, "get policy tree")
}
u := snapshotfs.NewUploader(rw)
man, err := u.Upload(ctx, root, policyTree, si)
if err != nil {
return nil, errors.Wrap(err, "uploading data")
}
if _, err := snapshot.SaveSnapshot(ctx, rw, man); err != nil {
return nil, errors.Wrap(err, "saving snapshot")
}
if err := rw.Flush(ctx); err != nil {
return nil, errors.Wrap(err, "flushing writer")
}
res := manifestToStats(man)
return &res, nil
}

View File

@ -50,8 +50,11 @@ type KopiaIntegrationSuite struct {
}
func TestKopiaIntegrationSuite(t *testing.T) {
if err := ctesting.RunOnAny(ctesting.CORSO_CI_TESTS); err != nil {
t.Skip(err)
if err := ctesting.RunOnAny(
ctesting.CORSO_CI_TESTS,
ctesting.CORSO_KOPIA_WRAPPER_TESTS,
); err != nil {
t.Skip()
}
suite.Run(t, new(KopiaIntegrationSuite))
@ -71,3 +74,22 @@ func (suite *KopiaIntegrationSuite) TestCloseTwiceDoesNotCrash() {
assert.Nil(suite.T(), k.rep)
assert.NoError(suite.T(), k.Close(ctx))
}
func (suite *KopiaIntegrationSuite) TestBackupCollections() {
ctx := context.Background()
timeOfTest := ctesting.LogTimeOfTest(suite.T())
k, err := openKopiaRepo(ctx, "init-s3-"+timeOfTest)
assert.NoError(suite.T(), err)
defer func() {
assert.NoError(suite.T(), k.Close(ctx))
}()
stats, err := k.BackupCollections(ctx, nil)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), stats.TotalFileCount, 0)
assert.Equal(suite.T(), stats.TotalDirectoryCount, 1)
assert.Equal(suite.T(), stats.IgnoredErrorCount, 0)
assert.Equal(suite.T(), stats.ErrorCount, 0)
assert.False(suite.T(), stats.Incomplete)
}

View File

@ -13,6 +13,7 @@ const (
CORSO_CI_TESTS = "CORSO_CI_TESTS"
CORSO_GRAPH_CONNECTOR_TESTS = "CORSO_GRAPH_CONNECTOR_TESTS"
CORSO_REPOSITORY_TESTS = "CORSO_REPOSITORY_TESTS"
CORSO_KOPIA_WRAPPER_TESTS = "CORSO_KOPIA_WRAPPER_TESTS"
)
// RunOnAny takes in a list of env variable names and returns