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