github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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, "all-machines.log")
    63  	touch(dirname, "machine-"+machineID+".log")
    64  
    65  	dirname = mkdir("/etc/init")
    66  	touch(dirname, "jujud-machine-"+machineID+".conf")
    67  	touch(dirname, "juju-db.conf")
    68  
    69  	dirname = mkdir("/etc/rsyslog.d")
    70  	touch(dirname, "spam-juju.conf")
    71  
    72  	dirname = mkdir("/home/ubuntu/.ssh")
    73  	touch(dirname, "authorized_keys")
    74  }
    75  
    76  func (s *filesSuite) checkSameStrings(c *gc.C, actual, expected []string) {
    77  	sActual := set.NewStrings(actual...)
    78  	sExpected := set.NewStrings(expected...)
    79  
    80  	sActualOnly := sActual.Difference(sExpected)
    81  	sExpectedOnly := sExpected.Difference(sActual)
    82  
    83  	if !sActualOnly.IsEmpty() || !sExpectedOnly.IsEmpty() {
    84  		c.Error("strings mismatch")
    85  		onlyActual := sActualOnly.Values()
    86  		onlyExpected := sExpectedOnly.Values()
    87  		sort.Strings(onlyActual)
    88  		sort.Strings(onlyExpected)
    89  
    90  		if !sActualOnly.IsEmpty() {
    91  			c.Log("...unexpected values:")
    92  			for _, str := range onlyActual {
    93  				c.Log(" " + str)
    94  			}
    95  		}
    96  		if !sExpectedOnly.IsEmpty() {
    97  			c.Log("...missing values:")
    98  			for _, str := range onlyExpected {
    99  				c.Log(" " + str)
   100  			}
   101  		}
   102  	}
   103  }
   104  
   105  func (s *filesSuite) TestGetFilesToBackUpMachine0(c *gc.C) {
   106  	paths := backups.Paths{
   107  		DataDir: "/var/lib/juju",
   108  		LogsDir: "/var/log/juju",
   109  	}
   110  	s.createFiles(c, paths, s.root, "0")
   111  
   112  	files, err := backups.GetFilesToBackUp(s.root, &paths, "0")
   113  	c.Assert(err, jc.ErrorIsNil)
   114  
   115  	expected := []string{
   116  		filepath.Join(s.root, "/etc/init/juju-db.conf"),
   117  		filepath.Join(s.root, "/etc/init/jujud-machine-0.conf"),
   118  		filepath.Join(s.root, "/etc/rsyslog.d/spam-juju.conf"),
   119  		filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"),
   120  		filepath.Join(s.root, "/var/lib/juju/agents/machine-0.conf"),
   121  		filepath.Join(s.root, "/var/lib/juju/nonce.txt"),
   122  		filepath.Join(s.root, "/var/lib/juju/server.pem"),
   123  		filepath.Join(s.root, "/var/lib/juju/shared-secret"),
   124  		filepath.Join(s.root, "/var/lib/juju/system-identity"),
   125  		filepath.Join(s.root, "/var/lib/juju/tools"),
   126  		filepath.Join(s.root, "/var/log/juju/all-machines.log"),
   127  		filepath.Join(s.root, "/var/log/juju/machine-0.log"),
   128  	}
   129  	c.Check(files, jc.SameContents, expected)
   130  	s.checkSameStrings(c, files, expected)
   131  }
   132  
   133  func (s *filesSuite) TestDirectoriesCleaned(c *gc.C) {
   134  	recreatableFolder := filepath.Join(s.root, "recreate_me")
   135  	os.MkdirAll(recreatableFolder, os.FileMode(0755))
   136  	recreatableFolderInfo, err := os.Stat(recreatableFolder)
   137  	c.Assert(err, jc.ErrorIsNil)
   138  
   139  	recreatableFolder1 := filepath.Join(recreatableFolder, "recreate_me_too")
   140  	os.MkdirAll(recreatableFolder1, os.FileMode(0755))
   141  	recreatableFolder1Info, err := os.Stat(recreatableFolder1)
   142  	c.Assert(err, jc.ErrorIsNil)
   143  
   144  	deletableFolder := filepath.Join(recreatableFolder, "dont_recreate_me")
   145  	os.MkdirAll(deletableFolder, os.FileMode(0755))
   146  
   147  	deletableFile := filepath.Join(recreatableFolder, "delete_me")
   148  	fh, err := os.Create(deletableFile)
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	defer fh.Close()
   151  
   152  	deletableFile1 := filepath.Join(recreatableFolder1, "delete_me.too")
   153  	fhr, err := os.Create(deletableFile1)
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	defer fhr.Close()
   156  
   157  	s.PatchValue(backups.ReplaceableFolders, func() (map[string]os.FileMode, error) {
   158  		replaceables := map[string]os.FileMode{}
   159  		for _, replaceable := range []string{
   160  			recreatableFolder,
   161  			recreatableFolder1,
   162  		} {
   163  			dirStat, err := os.Stat(replaceable)
   164  			if err != nil {
   165  				return map[string]os.FileMode{}, errors.Annotatef(err, "cannot stat %q", replaceable)
   166  			}
   167  			replaceables[replaceable] = dirStat.Mode()
   168  		}
   169  		return replaceables, nil
   170  	})
   171  
   172  	err = backups.PrepareMachineForRestore()
   173  	c.Assert(err, jc.ErrorIsNil)
   174  
   175  	_, err = os.Stat(deletableFolder)
   176  	c.Assert(err, gc.Not(gc.IsNil))
   177  	c.Assert(os.IsNotExist(err), gc.Equals, true)
   178  
   179  	recreatedFolderInfo, err := os.Stat(recreatableFolder)
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	c.Assert(recreatableFolderInfo.Mode(), gc.Equals, recreatedFolderInfo.Mode())
   182  	c.Assert(recreatableFolderInfo.Sys().(*syscall.Stat_t).Ino, gc.Not(gc.Equals), recreatedFolderInfo.Sys().(*syscall.Stat_t).Ino)
   183  
   184  	recreatedFolder1Info, err := os.Stat(recreatableFolder1)
   185  	c.Assert(err, jc.ErrorIsNil)
   186  	c.Assert(recreatableFolder1Info.Mode(), gc.Equals, recreatedFolder1Info.Mode())
   187  	c.Assert(recreatableFolder1Info.Sys().(*syscall.Stat_t).Ino, gc.Not(gc.Equals), recreatedFolder1Info.Sys().(*syscall.Stat_t).Ino)
   188  }
   189  
   190  func (s *filesSuite) TestGetFilesToBackUpMachine10(c *gc.C) {
   191  	paths := backups.Paths{
   192  		DataDir: "/var/lib/juju",
   193  		LogsDir: "/var/log/juju",
   194  	}
   195  	s.createFiles(c, paths, s.root, "10")
   196  
   197  	files, err := backups.GetFilesToBackUp(s.root, &paths, "10")
   198  	c.Assert(err, jc.ErrorIsNil)
   199  
   200  	expected := []string{
   201  		filepath.Join(s.root, "/etc/init/juju-db.conf"),
   202  		filepath.Join(s.root, "/etc/init/jujud-machine-10.conf"),
   203  		filepath.Join(s.root, "/etc/rsyslog.d/spam-juju.conf"),
   204  		filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"),
   205  		filepath.Join(s.root, "/var/lib/juju/agents/machine-10.conf"),
   206  		filepath.Join(s.root, "/var/lib/juju/nonce.txt"),
   207  		filepath.Join(s.root, "/var/lib/juju/server.pem"),
   208  		filepath.Join(s.root, "/var/lib/juju/shared-secret"),
   209  		filepath.Join(s.root, "/var/lib/juju/system-identity"),
   210  		filepath.Join(s.root, "/var/lib/juju/tools"),
   211  		filepath.Join(s.root, "/var/log/juju/all-machines.log"),
   212  		filepath.Join(s.root, "/var/log/juju/machine-10.log"),
   213  	}
   214  	c.Check(files, jc.SameContents, expected)
   215  	s.checkSameStrings(c, files, expected)
   216  }
   217  
   218  func (s *filesSuite) TestGetFilesToBackUpMissing(c *gc.C) {
   219  	paths := backups.Paths{
   220  		DataDir: "/var/lib/juju",
   221  		LogsDir: "/var/log/juju",
   222  	}
   223  	s.createFiles(c, paths, s.root, "0")
   224  
   225  	missing := []string{
   226  		"/var/lib/juju/nonce.txt",
   227  		"/home/ubuntu/.ssh/authorized_keys",
   228  		"/var/log/juju/all-machines.log",
   229  		"/var/log/juju/machine-0.log",
   230  	}
   231  	for _, filename := range missing {
   232  		err := os.Remove(filepath.Join(s.root, filename))
   233  		c.Assert(err, jc.ErrorIsNil)
   234  	}
   235  
   236  	files, err := backups.GetFilesToBackUp(s.root, &paths, "0")
   237  	c.Assert(err, jc.ErrorIsNil)
   238  
   239  	expected := []string{
   240  		filepath.Join(s.root, "/etc/init/juju-db.conf"),
   241  		filepath.Join(s.root, "/etc/init/jujud-machine-0.conf"),
   242  		filepath.Join(s.root, "/etc/rsyslog.d/spam-juju.conf"),
   243  		filepath.Join(s.root, "/var/lib/juju/agents/machine-0.conf"),
   244  		filepath.Join(s.root, "/var/lib/juju/server.pem"),
   245  		filepath.Join(s.root, "/var/lib/juju/shared-secret"),
   246  		filepath.Join(s.root, "/var/lib/juju/system-identity"),
   247  		filepath.Join(s.root, "/var/lib/juju/tools"),
   248  	}
   249  	// This got re-created.
   250  	expected = append(expected, filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"))
   251  	c.Check(files, jc.SameContents, expected)
   252  	s.checkSameStrings(c, files, expected)
   253  }