Skip to content

Commit

Permalink
Add Create() to the backups abstraction.
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsnowcurrently committed Sep 8, 2014
1 parent 2afaa2c commit a9512ff
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
46 changes: 46 additions & 0 deletions state/backups/backups.go
Expand Up @@ -6,14 +6,28 @@
package backups

import (
"github.com/juju/errors"
"github.com/juju/loggo"
"github.com/juju/utils/filestorage"

"github.com/juju/juju/state/backups/db"
"github.com/juju/juju/state/backups/files"
"github.com/juju/juju/state/backups/metadata"
)

var logger = loggo.GetLogger("juju.state.backups")

var (
getFilesToBackUp = files.GetFilesToBackUp
getDBDumper (func(db.ConnInfo) db.Dumper) = db.NewDumper
runCreate = create
)

// Backups is an abstraction around all juju backup-related functionality.
type Backups interface {
// Create creates and stores a new juju backup archive and returns
// its associated metadata.
Create(dbInfo *db.ConnInfo, origin *metadata.Origin, notes string) (*metadata.Metadata, error)
}

type backups struct {
Expand All @@ -28,3 +42,35 @@ func NewBackups(stor filestorage.FileStorage) Backups {
}
return &b
}

// Create creates and stores a new juju backup archive and returns
// its associated metadata.
func (b *backups) Create(dbInfo *db.ConnInfo, origin *metadata.Origin, notes string) (*metadata.Metadata, error) {
// Prep the metadata.
meta := metadata.NewMetadata(*origin, notes, nil)

// Create the archive.
filesToBackUp, err := getFilesToBackUp("")
if err != nil {
return nil, errors.Annotate(err, "error listing files to back up")
}
dumper := getDBDumper(*dbInfo)
args := createArgs{filesToBackUp, dumper}
result, err := runCreate(&args)
if err != nil {
return nil, errors.Annotate(err, "error creating backup archive")
}
defer result.archiveFile.Close()

// Store the archive.
err = meta.Finish(result.size, result.checksum, "", nil)
if err != nil {
return nil, errors.Annotate(err, "error updating metadata")
}
_, err = b.storage.Add(meta, result.archiveFile)
if err != nil {
return nil, errors.Annotate(err, "error storing backup archive")
}

return meta, nil
}
62 changes: 62 additions & 0 deletions state/backups/backups_test.go
Expand Up @@ -4,10 +4,16 @@
package backups_test

import (
"bytes"
"io/ioutil"

jc "github.com/juju/testing/checkers"
"github.com/juju/utils/filestorage"
gc "launchpad.net/gocheck"

"github.com/juju/juju/state/backups"
"github.com/juju/juju/state/backups/db"
"github.com/juju/juju/state/backups/metadata"
"github.com/juju/juju/testing"
)

Expand Down Expand Up @@ -35,3 +41,59 @@ func (s *backupsSuite) TestNewBackups(c *gc.C) {

c.Check(api, gc.NotNil)
}

func (s *backupsSuite) TestCreateOkay(c *gc.C) {
// Patch the internals.
archiveFile := ioutil.NopCloser(bytes.NewBufferString("<compressed tarball>"))
result := backups.NewTestCreateResult(archiveFile, 10, "<checksum>")
received, testCreate := backups.NewTestCreate(result, nil)
s.PatchValue(backups.RunCreate, testCreate)

rootDir := "<was never set>"
s.PatchValue(backups.GetFilesToBackUp, func(root string) ([]string, error) {
rootDir = root
return []string{"<some file>"}, nil
})

var receivedDBInfo *db.ConnInfo
s.PatchValue(backups.GetDBDumper, func(info db.ConnInfo) db.Dumper {
receivedDBInfo = &info
return nil
})

// Run the backup.
dbInfo := &db.ConnInfo{"a", "b", "c"}
origin := metadata.NewOrigin("<env ID>", "<machine ID>", "<hostname>")
meta, err := s.api.Create(dbInfo, origin, "some notes")

// Test the call values.
filesToBackUp, _ := backups.ExposeCreateArgs(received)
c.Check(filesToBackUp, jc.SameContents, []string{"<some file>"})

err = receivedDBInfo.Validate()
c.Assert(err, gc.IsNil)
c.Check(receivedDBInfo.Address, gc.Equals, "a")
c.Check(receivedDBInfo.Username, gc.Equals, "b")
c.Check(receivedDBInfo.Password, gc.Equals, "c")

c.Check(rootDir, gc.Equals, "")

// Check the resulting metadata.
c.Check(meta.ID(), gc.Not(gc.Equals), "")
c.Check(meta.Size(), gc.Equals, int64(10))
c.Check(meta.Checksum(), gc.Equals, "<checksum>")
c.Check(meta.Stored(), gc.Equals, true)
metaOrigin := meta.Origin()
c.Check(metaOrigin.Environment(), gc.Equals, "<env ID>")
c.Check(metaOrigin.Machine(), gc.Equals, "<machine ID>")
c.Check(metaOrigin.Hostname(), gc.Equals, "<hostname>")
c.Check(meta.Notes(), gc.Equals, "some notes")

// Check the file storage.
storedMeta, storedFile, err := s.storage.Get(meta.ID())
c.Check(err, gc.IsNil)
c.Check(storedMeta, gc.DeepEquals, meta)
data, err := ioutil.ReadAll(storedFile)
c.Assert(err, gc.IsNil)
c.Check(string(data), gc.Equals, "<compressed tarball>")
}
31 changes: 31 additions & 0 deletions state/backups/export_test.go
Expand Up @@ -11,6 +11,10 @@ import (

var (
Create = create

GetFilesToBackUp = &getFilesToBackUp
GetDBDumper = &getDBDumper
RunCreate = &runCreate
)

func ExposeCreateResult(result *createResult) (io.ReadCloser, int64, string) {
Expand All @@ -24,3 +28,30 @@ func NewTestCreateArgs(filesToBackUp []string, db db.Dumper) *createArgs {
}
return &args
}

func ExposeCreateArgs(args *createArgs) ([]string, db.Dumper) {
return args.filesToBackUp, args.db
}

func NewTestCreateResult(file io.ReadCloser, size int64, checksum string) *createResult {
result := createResult{
archiveFile: file,
size: size,
checksum: checksum,
}
return &result
}

func NewTestCreate(result *createResult, err error) (*createArgs, func(*createArgs) (*createResult, error)) {
var received createArgs

testCreate := func(args *createArgs) (*createResult, error) {
received = *args
if err != nil {
return nil, err
}
return result, nil
}

return &received, testCreate
}

0 comments on commit a9512ff

Please sign in to comment.