github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/environs/configstore/disk_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package configstore_test 5 6 import ( 7 "fmt" 8 "io/ioutil" 9 "os" 10 "os/user" 11 "path/filepath" 12 "strings" 13 "syscall" 14 15 "github.com/juju/errors" 16 jc "github.com/juju/testing/checkers" 17 gc "launchpad.net/gocheck" 18 19 "github.com/juju/juju/environs/configstore" 20 "github.com/juju/juju/testing" 21 ) 22 23 var _ = gc.Suite(&diskInterfaceSuite{}) 24 25 type diskInterfaceSuite struct { 26 interfaceSuite 27 dir string 28 } 29 30 func (s *diskInterfaceSuite) SetUpTest(c *gc.C) { 31 s.dir = c.MkDir() 32 s.NewStore = func(c *gc.C) configstore.Storage { 33 store, err := configstore.NewDisk(s.dir) 34 c.Assert(err, gc.IsNil) 35 return store 36 } 37 } 38 39 // storePath returns the path to the environment info 40 // for the named environment in the given directory. 41 // If envName is empty, it returns the path 42 // to the info files' containing directory. 43 func storePath(dir string, envName string) string { 44 path := filepath.Join(dir, "environments") 45 if envName != "" { 46 path = filepath.Join(path, envName+".jenv") 47 } 48 return path 49 } 50 51 func (s *diskInterfaceSuite) TearDownTest(c *gc.C) { 52 s.NewStore = nil 53 // Check that no stray temp files have been left behind 54 entries, err := ioutil.ReadDir(storePath(s.dir, "")) 55 c.Assert(err, gc.IsNil) 56 for _, entry := range entries { 57 if !strings.HasSuffix(entry.Name(), ".jenv") { 58 c.Errorf("found possible stray temp file %q", entry.Name()) 59 } 60 } 61 } 62 63 var _ = gc.Suite(&diskStoreSuite{}) 64 65 type diskStoreSuite struct { 66 testing.BaseSuite 67 } 68 69 func (*diskStoreSuite) TestNewDisk(c *gc.C) { 70 dir := c.MkDir() 71 store, err := configstore.NewDisk(filepath.Join(dir, "foo")) 72 c.Assert(err, jc.Satisfies, os.IsNotExist) 73 c.Assert(store, gc.IsNil) 74 75 store, err = configstore.NewDisk(filepath.Join(dir)) 76 c.Assert(err, gc.IsNil) 77 c.Assert(store, gc.NotNil) 78 } 79 80 var sampleInfo = ` 81 user: rog 82 password: guessit 83 state-servers: 84 - example.com 85 - kremvax.ru 86 ca-cert: 'first line 87 88 second line' 89 bootstrap-config: 90 secret: blah 91 arble: bletch 92 `[1:] 93 94 func (*diskStoreSuite) TestRead(c *gc.C) { 95 dir := c.MkDir() 96 err := os.Mkdir(storePath(dir, ""), 0700) 97 c.Assert(err, gc.IsNil) 98 err = ioutil.WriteFile(storePath(dir, "someenv"), []byte(sampleInfo), 0666) 99 c.Assert(err, gc.IsNil) 100 store, err := configstore.NewDisk(dir) 101 c.Assert(err, gc.IsNil) 102 info, err := store.ReadInfo("someenv") 103 c.Assert(err, gc.IsNil) 104 c.Assert(info.Initialized(), jc.IsTrue) 105 c.Assert(info.APICredentials(), gc.DeepEquals, configstore.APICredentials{ 106 User: "rog", 107 Password: "guessit", 108 }) 109 c.Assert(info.APIEndpoint(), gc.DeepEquals, configstore.APIEndpoint{ 110 Addresses: []string{"example.com", "kremvax.ru"}, 111 CACert: "first line\nsecond line", 112 }) 113 c.Assert(info.Location(), gc.Equals, fmt.Sprintf("file %q", dir+"/environments/someenv.jenv")) 114 c.Assert(info.BootstrapConfig(), gc.DeepEquals, map[string]interface{}{ 115 "secret": "blah", 116 "arble": "bletch", 117 }) 118 } 119 120 func (*diskStoreSuite) TestReadNotFound(c *gc.C) { 121 dir := c.MkDir() 122 store, err := configstore.NewDisk(dir) 123 c.Assert(err, gc.IsNil) 124 info, err := store.ReadInfo("someenv") 125 c.Assert(err, jc.Satisfies, errors.IsNotFound) 126 c.Assert(info, gc.IsNil) 127 } 128 129 func (*diskStoreSuite) TestCreate(c *gc.C) { 130 dir := c.MkDir() 131 store, err := configstore.NewDisk(dir) 132 c.Assert(err, gc.IsNil) 133 134 // Create some new environment info. 135 info, err := store.CreateInfo("someenv") 136 c.Assert(err, gc.IsNil) 137 c.Assert(info.APIEndpoint(), gc.DeepEquals, configstore.APIEndpoint{}) 138 c.Assert(info.APICredentials(), gc.DeepEquals, configstore.APICredentials{}) 139 c.Assert(info.Initialized(), jc.IsFalse) 140 data, err := ioutil.ReadFile(storePath(dir, "someenv")) 141 c.Assert(err, gc.IsNil) 142 c.Assert(data, gc.HasLen, 0) 143 144 // Check that we can't create it twice. 145 info, err = store.CreateInfo("someenv") 146 c.Assert(err, gc.Equals, configstore.ErrEnvironInfoAlreadyExists) 147 c.Assert(info, gc.IsNil) 148 149 // Check that we can read it again. 150 info, err = store.ReadInfo("someenv") 151 c.Assert(err, gc.IsNil) 152 c.Assert(info.Initialized(), jc.IsFalse) 153 } 154 155 func (s *diskStoreSuite) TestCreatePermissions(c *gc.C) { 156 // Even though it doesn't test the actual chown, it does test the code path. 157 user, err := user.Current() 158 c.Assert(err, gc.IsNil) 159 s.PatchEnvironment("SUDO_UID", user.Uid) 160 s.PatchEnvironment("SUDO_GID", user.Gid) 161 162 dir := c.MkDir() 163 store, err := configstore.NewDisk(dir) 164 c.Assert(err, gc.IsNil) 165 166 // Create some new environment info. 167 _, err = store.CreateInfo("someenv") 168 c.Assert(err, gc.IsNil) 169 170 checkPath := func(path string) { 171 stat, err := os.Stat(path) 172 c.Assert(err, gc.IsNil) 173 c.Assert(fmt.Sprint(stat.Sys().(*syscall.Stat_t).Uid), gc.Equals, user.Uid) 174 c.Assert(fmt.Sprint(stat.Sys().(*syscall.Stat_t).Gid), gc.Equals, user.Gid) 175 } 176 checkPath(storePath(dir, "")) 177 checkPath(storePath(dir, "someenv")) 178 } 179 180 func (*diskStoreSuite) TestWriteTempFileFails(c *gc.C) { 181 dir := c.MkDir() 182 store, err := configstore.NewDisk(dir) 183 c.Assert(err, gc.IsNil) 184 185 info, err := store.CreateInfo("someenv") 186 c.Assert(err, gc.IsNil) 187 188 // Make the directory non-writable 189 err = os.Chmod(storePath(dir, ""), 0555) 190 c.Assert(err, gc.IsNil) 191 192 err = info.Write() 193 c.Assert(err, gc.ErrorMatches, "cannot create temporary file: .*") 194 195 // Make the directory writable again so that gocheck can clean it up. 196 err = os.Chmod(storePath(dir, ""), 0777) 197 c.Assert(err, gc.IsNil) 198 } 199 200 func (*diskStoreSuite) TestRenameFails(c *gc.C) { 201 dir := c.MkDir() 202 store, err := configstore.NewDisk(dir) 203 c.Assert(err, gc.IsNil) 204 205 info, err := store.CreateInfo("someenv") 206 c.Assert(err, gc.IsNil) 207 208 // Replace the file by an directory which can't be renamed over. 209 path := storePath(dir, "someenv") 210 err = os.Remove(path) 211 c.Assert(err, gc.IsNil) 212 err = os.Mkdir(path, 0777) 213 c.Assert(err, gc.IsNil) 214 215 err = info.Write() 216 c.Assert(err, gc.ErrorMatches, "cannot rename new environment info file: .*") 217 } 218 219 func (*diskStoreSuite) TestDestroyRemovesFiles(c *gc.C) { 220 dir := c.MkDir() 221 store, err := configstore.NewDisk(dir) 222 c.Assert(err, gc.IsNil) 223 224 info, err := store.CreateInfo("someenv") 225 c.Assert(err, gc.IsNil) 226 227 _, err = os.Stat(storePath(dir, "someenv")) 228 c.Assert(err, gc.IsNil) 229 230 err = info.Destroy() 231 c.Assert(err, gc.IsNil) 232 233 _, err = os.Stat(storePath(dir, "someenv")) 234 c.Assert(err, jc.Satisfies, os.IsNotExist) 235 236 err = info.Destroy() 237 c.Assert(err, gc.ErrorMatches, "environment info has already been removed") 238 }