github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/backups/files_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // +build !windows
     5  
     6  package backups_test
     7  
     8  import (
     9  	"os"
    10  	"path/filepath"
    11  	"sort"
    12  	"syscall"
    13  
    14  	"github.com/juju/errors"
    15  	jc "github.com/juju/testing/checkers"
    16  	"github.com/juju/utils/set"
    17  	gc "gopkg.in/check.v1"
    18  
    19  	"github.com/juju/juju/state/backups"
    20  	"github.com/juju/juju/testing"
    21  )
    22  
    23  var _ = gc.Suite(&filesSuite{})
    24  
    25  type filesSuite struct {
    26  	testing.BaseSuite
    27  	root string
    28  }
    29  
    30  func (s *filesSuite) SetUpTest(c *gc.C) {
    31  	s.BaseSuite.SetUpTest(c)
    32  
    33  	s.root = c.MkDir()
    34  }
    35  
    36  // createFiles preps the fake FS. The files are all created relative to
    37  // the given root.
    38  func (s *filesSuite) createFiles(c *gc.C, paths backups.Paths, root, machineID string) {
    39  	mkdir := func(path string) string {
    40  		dirname := filepath.Join(root, path)
    41  		os.MkdirAll(dirname, 0777)
    42  		return dirname
    43  	}
    44  	touch := func(dirname, name string) {
    45  		path := filepath.Join(dirname, name)
    46  		file, err := os.Create(path)
    47  		c.Assert(err, jc.ErrorIsNil)
    48  		file.Close()
    49  	}
    50  
    51  	dirname := mkdir(paths.DataDir)
    52  	touch(dirname, "system-identity")
    53  	touch(dirname, "nonce.txt")
    54  	touch(dirname, "server.pem")
    55  	touch(dirname, "shared-secret")
    56  	mkdir(filepath.Join(paths.DataDir, "tools"))
    57  
    58  	dirname = mkdir(filepath.Join(paths.DataDir, "agents"))
    59  	touch(dirname, "machine-"+machineID+".conf")
    60  
    61  	dirname = mkdir(paths.LogsDir)
    62  	touch(dirname, "machine-"+machineID+".log")
    63  
    64  	dirname = mkdir("/home/ubuntu/.ssh")
    65  	touch(dirname, "authorized_keys")
    66  }
    67  
    68  func (s *filesSuite) checkSameStrings(c *gc.C, actual, expected []string) {
    69  	sActual := set.NewStrings(actual...)
    70  	sExpected := set.NewStrings(expected...)
    71  
    72  	sActualOnly := sActual.Difference(sExpected)
    73  	sExpectedOnly := sExpected.Difference(sActual)
    74  
    75  	if !sActualOnly.IsEmpty() || !sExpectedOnly.IsEmpty() {
    76  		c.Error("strings mismatch")
    77  		onlyActual := sActualOnly.Values()
    78  		onlyExpected := sExpectedOnly.Values()
    79  		sort.Strings(onlyActual)
    80  		sort.Strings(onlyExpected)
    81  
    82  		if !sActualOnly.IsEmpty() {
    83  			c.Log("...unexpected values:")
    84  			for _, str := range onlyActual {
    85  				c.Log(" " + str)
    86  			}
    87  		}
    88  		if !sExpectedOnly.IsEmpty() {
    89  			c.Log("...missing values:")
    90  			for _, str := range onlyExpected {
    91  				c.Log(" " + str)
    92  			}
    93  		}
    94  	}
    95  }
    96  
    97  func (s *filesSuite) TestGetFilesToBackUpMachine0(c *gc.C) {
    98  	paths := backups.Paths{
    99  		DataDir: "/var/lib/juju",
   100  		LogsDir: "/var/log/juju",
   101  	}
   102  	s.createFiles(c, paths, s.root, "0")
   103  
   104  	files, err := backups.GetFilesToBackUp(s.root, &paths, "0")
   105  	c.Assert(err, jc.ErrorIsNil)
   106  
   107  	expected := []string{
   108  		filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"),
   109  		filepath.Join(s.root, "/var/lib/juju/agents/machine-0.conf"),
   110  		filepath.Join(s.root, "/var/lib/juju/nonce.txt"),
   111  		filepath.Join(s.root, "/var/lib/juju/server.pem"),
   112  		filepath.Join(s.root, "/var/lib/juju/shared-secret"),
   113  		filepath.Join(s.root, "/var/lib/juju/system-identity"),
   114  		filepath.Join(s.root, "/var/lib/juju/tools"),
   115  		filepath.Join(s.root, "/var/log/juju/machine-0.log"),
   116  	}
   117  	c.Check(files, jc.SameContents, expected)
   118  	s.checkSameStrings(c, files, expected)
   119  }
   120  
   121  func (s *filesSuite) TestDirectoriesCleaned(c *gc.C) {
   122  	recreatableFolder := filepath.Join(s.root, "recreate_me")
   123  	os.MkdirAll(recreatableFolder, os.FileMode(0755))
   124  	recreatableFolderInfo, err := os.Stat(recreatableFolder)
   125  	c.Assert(err, jc.ErrorIsNil)
   126  
   127  	recreatableFolder1 := filepath.Join(recreatableFolder, "recreate_me_too")
   128  	os.MkdirAll(recreatableFolder1, os.FileMode(0755))
   129  	recreatableFolder1Info, err := os.Stat(recreatableFolder1)
   130  	c.Assert(err, jc.ErrorIsNil)
   131  
   132  	deletableFolder := filepath.Join(recreatableFolder, "dont_recreate_me")
   133  	os.MkdirAll(deletableFolder, os.FileMode(0755))
   134  
   135  	deletableFile := filepath.Join(recreatableFolder, "delete_me")
   136  	fh, err := os.Create(deletableFile)
   137  	c.Assert(err, jc.ErrorIsNil)
   138  	defer fh.Close()
   139  
   140  	deletableFile1 := filepath.Join(recreatableFolder1, "delete_me.too")
   141  	fhr, err := os.Create(deletableFile1)
   142  	c.Assert(err, jc.ErrorIsNil)
   143  	defer fhr.Close()
   144  
   145  	s.PatchValue(backups.ReplaceableFolders, func() (map[string]os.FileMode, error) {
   146  		replaceables := map[string]os.FileMode{}
   147  		for _, replaceable := range []string{
   148  			recreatableFolder,
   149  			recreatableFolder1,
   150  		} {
   151  			dirStat, err := os.Stat(replaceable)
   152  			if err != nil {
   153  				return map[string]os.FileMode{}, errors.Annotatef(err, "cannot stat %q", replaceable)
   154  			}
   155  			replaceables[replaceable] = dirStat.Mode()
   156  		}
   157  		return replaceables, nil
   158  	})
   159  
   160  	err = backups.PrepareMachineForRestore()
   161  	c.Assert(err, jc.ErrorIsNil)
   162  
   163  	_, err = os.Stat(deletableFolder)
   164  	c.Assert(err, gc.Not(gc.IsNil))
   165  	c.Assert(os.IsNotExist(err), gc.Equals, true)
   166  
   167  	recreatedFolderInfo, err := os.Stat(recreatableFolder)
   168  	c.Assert(err, jc.ErrorIsNil)
   169  	c.Assert(recreatableFolderInfo.Mode(), gc.Equals, recreatedFolderInfo.Mode())
   170  	c.Assert(recreatableFolderInfo.Sys().(*syscall.Stat_t).Ino, gc.Not(gc.Equals), recreatedFolderInfo.Sys().(*syscall.Stat_t).Ino)
   171  
   172  	recreatedFolder1Info, err := os.Stat(recreatableFolder1)
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	c.Assert(recreatableFolder1Info.Mode(), gc.Equals, recreatedFolder1Info.Mode())
   175  	c.Assert(recreatableFolder1Info.Sys().(*syscall.Stat_t).Ino, gc.Not(gc.Equals), recreatedFolder1Info.Sys().(*syscall.Stat_t).Ino)
   176  }
   177  
   178  func (s *filesSuite) TestGetFilesToBackUpMachine10(c *gc.C) {
   179  	paths := backups.Paths{
   180  		DataDir: "/var/lib/juju",
   181  		LogsDir: "/var/log/juju",
   182  	}
   183  	s.createFiles(c, paths, s.root, "10")
   184  
   185  	files, err := backups.GetFilesToBackUp(s.root, &paths, "10")
   186  	c.Assert(err, jc.ErrorIsNil)
   187  
   188  	expected := []string{
   189  		filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"),
   190  		filepath.Join(s.root, "/var/lib/juju/agents/machine-10.conf"),
   191  		filepath.Join(s.root, "/var/lib/juju/nonce.txt"),
   192  		filepath.Join(s.root, "/var/lib/juju/server.pem"),
   193  		filepath.Join(s.root, "/var/lib/juju/shared-secret"),
   194  		filepath.Join(s.root, "/var/lib/juju/system-identity"),
   195  		filepath.Join(s.root, "/var/lib/juju/tools"),
   196  		filepath.Join(s.root, "/var/log/juju/machine-10.log"),
   197  	}
   198  	c.Check(files, jc.SameContents, expected)
   199  	s.checkSameStrings(c, files, expected)
   200  }
   201  
   202  func (s *filesSuite) TestGetFilesToBackUpMissing(c *gc.C) {
   203  	paths := backups.Paths{
   204  		DataDir: "/var/lib/juju",
   205  		LogsDir: "/var/log/juju",
   206  	}
   207  	s.createFiles(c, paths, s.root, "0")
   208  
   209  	missing := []string{
   210  		"/var/lib/juju/nonce.txt",
   211  		"/home/ubuntu/.ssh/authorized_keys",
   212  		"/var/log/juju/machine-0.log",
   213  	}
   214  	for _, filename := range missing {
   215  		err := os.Remove(filepath.Join(s.root, filename))
   216  		c.Assert(err, jc.ErrorIsNil)
   217  	}
   218  
   219  	files, err := backups.GetFilesToBackUp(s.root, &paths, "0")
   220  	c.Assert(err, jc.ErrorIsNil)
   221  
   222  	expected := []string{
   223  		filepath.Join(s.root, "/var/lib/juju/agents/machine-0.conf"),
   224  		filepath.Join(s.root, "/var/lib/juju/server.pem"),
   225  		filepath.Join(s.root, "/var/lib/juju/shared-secret"),
   226  		filepath.Join(s.root, "/var/lib/juju/system-identity"),
   227  		filepath.Join(s.root, "/var/lib/juju/tools"),
   228  	}
   229  	// This got re-created.
   230  	expected = append(expected, filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"))
   231  	c.Check(files, jc.SameContents, expected)
   232  	s.checkSameStrings(c, files, expected)
   233  }