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 }