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 }